Какая разница между Application.ThreadException и AppDomain.CurrentDomain.UnhandledException?

Хорошо, это легко:

  • Чем отличается Application.ThreadException и AppDomain.CurrentDomain.UnhandledException?

  • Нужно ли обрабатывать оба?

Спасибо!

Ответ 1

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

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

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

Fwiw: "ThreadException" был очень плохим выбором имени. Он не имеет ничего общего с потоками.

Ответ 2

В приложениях, использующих 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.

Ответ 3

ОК - у меня это было передо мной, этот фрагмент кода из 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());
}

Ответ 4

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

Простой способ вызвать второй - создать приложение, не пытающееся... блокировать блоки и вызывать исключение.

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