В чем разница между Application.ThreadException и AppDomain.CurrentDomain.UnhandledException?

107

Хорошо, это просто:

  • В чем разница между Application.ThreadExceptionи
    AppDomain.CurrentDomain.UnhandledException?

  • Мне нужно обрабатывать оба?

Спасибо!

JohnIdol
источник

Ответы:

98

Application.ThreadException относится к Windows Forms. Winforms запускает обработчики событий в ответ на сообщения, отправленные ему Windows. Например, событие Click, я уверен, вы их знаете. Если такой обработчик событий генерирует исключение, то внутри цикла сообщений Winforms есть обратная остановка, которая перехватывает это исключение.

Эта остановка вызывает событие Application.ThreadException . Если вы не переопределите его, пользователь получит ThreadExceptionDialog . Это позволяет ему игнорировать исключение и продолжать работу вашей программы. Кстати, не самая лучшая идея.

Вы можете отключить это поведение, вызвав Application.SetUnhandledExceptionMode () в методе Main () в Program.cs. Без этой поддержки происходит обычное дело, когда поток умирает из-за необработанного исключения: срабатывает AppDomain.UnhandledException, и программа завершается.

Fwiw: «ThreadException» было очень неудачным выбором имени. Это не имеет ничего общего с потоками.

Ганс Пассан
источник
И как предотвратить сбой приложения WinForms при возникновении файла Application.ThreadException. Я поднял вопрос по этому поводу [здесь ] с помощью моего небольшого кода C #.
Mahesha999
2
Я всегда читаю это как исключение Application-thread, учитывая, что winforms привязан к одному потоку.
Gusdor
36

Из источника :

В приложениях, использующих Windows Forms, необработанные исключения в основном потоке приложения вызывают Application.ThreadException событие. Если это событие обрабатывается, поведение по умолчанию таково, что необработанное исключение не завершает работу приложения, хотя приложение остается в неизвестном состоянии. В этом случае UnhandledException событие не возникает. Это поведение можно изменить с помощью файла конфигурации приложения или с помощью Application.SetUnhandledExceptionModeметода изменения режима UnhandledExceptionMode.ThrowExceptionдо ThreadException подключения обработчика событий. Это относится только к основному потоку приложения. UnhandledException Событие вызывается для необработанных исключений выброшенных в других потоках.

Начиная с Visual Studio 2005 , платформа приложений Visual Basic предоставляет другое событие для необработанных исключений в основном потоке приложения - WindowsFormsApplicationBase.UnhandledException. Это событие имеет объект аргументов события с тем же именем, что и объект аргументов события, используемый AppDomain.UnhandledException, но с другими свойствами. В частности, этот объект аргументов события имеет ExitApplicationсвойство, которое позволяет приложению продолжать работу, игнорируя необработанное исключение (и оставляя приложение в неизвестном состоянии). В этом случае событие AppDomain.UnhandledException не возникает.

Application.ThreadExceptionможет быть обнаружен, и приложение может продолжить работу (в целом это не лучшая идея, но для приложения, например, периодически выполняющего некоторые действия, это хорошее решение).

Чтобы перехватить исключения, возникающие в потоках, не созданных и не принадлежащих Windows Forms, используйте AppDomain.UnhandledException. Это позволяет приложению регистрировать информацию об исключении до того, как системный обработчик по умолчанию сообщит об исключении пользователю и завершит работу приложения.
Обработка этого исключения не препятствует завершению работы приложения.
Максимум, что можно было сделать (данные программы могут быть повреждены, если исключения не обрабатываются), - это сохранить данные программы для последующего восстановления. После этого домен приложения выгружается, и приложение завершается.

Начиная с .NET 4 , это событие не возникает для исключений, которые нарушают состояние процесса, таких как переполнение стека или нарушения доступа, если только обработчик событий не является критичным для безопасности и не имеет HandleProcessCorruptedStateExceptionsAttribute атрибут.

Для получения дополнительных сведений см. MSDN .

Серхио
источник
18

Хорошо - у меня это было передо мной, этот фрагмент кода из msdn довольно понятен:

public static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new 
        ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

    // Set the unhandled exception mode to force all Windows Forms 
    // errors to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    // Runs the application.
    Application.Run(new ErrorHandlerForm());
}
JohnIdol
источник
3
это контрастирует с другим ответом serhio, когда он говорит: UnhandledExceptionMode.ThrowException должен быть установлен до подключения обработчика событий ThreadException. Не уверен, что порядок действительно имеет значение ...
Давид Пирас
@DavidePiras, да, и есть кое-что более темное. SetUnhandledException в моем случае не имеет значения.
nawfal
0

Дело в том, что ThreadExceptionпроисходит из-за проблемы с вашим потоком, Unhandled Exceptionзапускается, если ваш код генерирует исключение, которое не обрабатывается.

Самый простой способ вызвать второй - создать приложение без блоков try ... catch и выбросить исключение.

Теперь, если вам нужна страховка, вы можете справиться с ними обоими, однако, если вы exceptionsправильно UnhandledExceptionпоймаете и обработаете ее, вам не понадобится обработчик, поскольку это своего рода улов.

Джошуа Кавл
источник
спасибо - я не слишком ясно понял, если бы обрабатывать UnhandledException, я бы также поймал ThreadException - что, похоже, не так
JohnIdol