Я имею дело с запуском другого приложения, которое очень нестабильно и сильно вылетает.
Вот моя текущая настройка, само выполнение происходит в T:
var threadEndEvent = new ManualResetEventSlim(false);
var executionThread = new Thread(async () =>
{
try
{
await T();
}
catch (Exception x)
{
//deal with exceptions...
}
finally
{
threadEndEvent.Set();
}
}
У меня таймер работает по таймауту:
timer.Elapsed += (sender, args) =>
{
var result = Task.Run(() => executionThread.Abort()).Wait(new TimeSpan(0, 0, 30);
//log if aborting was succesful and other info...
threadEndEvent.Set();
}
После этого делаю так:
executionThread.Start();
threadEndEvent.Wait(timeoutSpan)
В конце концов, происходит одно из двух: либо поток завершается, либо после тайм-аута он пытается его прервать, регистрирует все, что произошло, и продолжает работу.
Кажется, что в большинстве случаев это работает нормально, однако, когда я запускаю какое-то другое приложение, оно вылетает, отображая стандартную ошибку, например
"exe stopped working, Windows can check online for the solution to the problem"
прерывание никогда не происходит, и все зависает.
Я запускаю это приложение в T следующим образом:
var process = new Process
{
StartInfo =
{
//Specify path to exe, arguments, etc...
}
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
Я знаю, что WaitForExit блокирует потоки, однако он выполняется в отдельном потоке executionThread, поэтому я не уверен, почему выполнение зависает.
Что мне здесь не хватает? Как мне сделать так, чтобы он продолжал работать после тайм-аута, что бы ни случилось?
@pstrjds обновленный вопрос, я не пытаюсь убить внешнее приложение, мне просто нужно, чтобы мой код не зависал и не двигался дальше, если произошел сбой.
Вы пробовали отлаживать и ломать при возникновении этой проблемы? Мне интересно, может ли он быть заблокирован в одном из ваших обработчиков выходных событий. Это немного странное предположение, но Process.WaitForExit должен вернуться, когда приложение выйдет из строя но, он будет ждать завершения всех обработчиков перенаправления вывода. Я бы подумал, что ваш код прерывания потока все равно будет запускать и уничтожать этот поток, но возможно, что существует асинхронная операция чтения, которая зависает при сбое приложения.
@pstrjds Как ни странно, судя по логам, событие timer.Elapsed никогда не срабатывает изначально - вроде все зависло. Отладка сейчас проблематична, но я обновлю вопрос, как только смогу это сделать.
Основываясь на том, что вы описали как происходящее, я полностью сброшен с толку, если у вас нет чего-то еще, что блокирует ваш основной поток. У вас есть вызов Wait для этого события, но у вас есть тайм-аут, поэтому я ожидаю, что код продолжится, даже если таймер не сработал, и прервет поток и установит дескриптор события. Вы все равно должны пройти мимо этого дескриптора события. Я подозреваю, что что-то еще происходит ИЛИ, это ваше приложение разбилось и выскочило это диалоговое окно? Вы установили необработанное исключение обработчики в приложении ваш?





В конце концов нашел решение. К сожалению, отладчик не работает должным образом, поэтому детали будут очень расплывчатыми.
Как только я начал копать глубже, я обнаружил, что T работает следующим образом:
var executingThread = new Thread(()=>{
//process code mentioned in question...
});
executingThread.Start();
executingThread.Join();
Не уверен, почему это так, я имею дело с недокументированным устаревшим кодом.
В любом случае, как только я удалил лишний код потока, исключения перехватываются правильно, и ничего не зависает.
Не уверен, почему именно создание дополнительного потока делает исключения невозможными (никогда не видел этой проблемы, когда этот код работал на .NET Framework), но если у вас возникла аналогичная проблема, это может быть решением.
Я немного смущен. Иногда происходит сбой в вашем потоке или это внешнее приложение, которое вы запускаете изнутри этого потока? Похоже, вы запускаете приложение. Я не уверен, как убийство потока убьет внешнее приложение даже после тайм-аута. Не могли бы вы объяснить немного больше или показать образец кода вашего потока / запуска приложения?