У чому різниця між Application.ThreadException і AppDomain.CurrentDomain.UnhandledException?


107

Добре, це легко:

  • Яка різниця між Application.ThreadExceptionі
    AppDomain.CurrentDomain.UnhandledException?

  • Чи потрібно обробляти обидва?

Дякую!

Відповіді:


98

Application.ThreadException характерний лише для Windows Forms. Winforms запускає обробників подій у відповідь на повідомлення, надіслані йому Windows. Наприклад, подія Click, я впевнений, що ви їх знаєте. Якщо такий обробник подій кидає виняток, всередині циклу повідомлень Winforms є зворотна зупинка, яка фіксує це виключення.

Цей запуск спрацьовує подія Application.ThreadException . Якщо ви не перекриєте це, користувач отримає ThreadExceptionDialog . Що дозволяє йому ігнорувати виняток і продовжувати запускати вашу програму. Не чудова ідея btw.

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

Fwiw: "ThreadException" був дуже поганим вибором імені. Це не має нічого спільного з нитками.


І як зупинити програму WinForms від збоїв при появі Application.ThreadException. Я поставив питання для цього [тут ] зі своїм маленьким кодом C #.
Mahesha999

2
Я завжди читаю це як виняток для нитки додатків, враховуючи, що winforms прив'язаний до одного потоку.
Гусдор

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());
}

3
це на відміну від іншої відповіді серхіо, коли він говорить: UnhandledExceptionMode.ThrowException слід встановити перед тим, як підключити обробник подій ThreadException. Не впевнений, чи дійсно замовлення має значення ...
Давіде Пірас

@DavidePiras так, і є щось більш каламутне. SetUnhandledException, схоже, не має жодного значення в моєму випадку.
nawfal

0

Ну, справа в тому, що ThreadExceptionвиникає через проблему з вашою потоком, Unhandled Exceptionвимкнено, якщо код викидає виняток, який не обробляється.

Найпростіший спосіб викликати другий - створити додаток без спроб ... ловити блоки та кидати виняток.

Тепер, якщо вам потрібна страховка, ви можете впоратися з ними обома, однак, якщо ви захоплюєте та обробляєте їх exceptionsправильно, тоді вам не потрібен UnhandledExceptionобробник, оскільки це як би спійманий все.


спасибі - те, про що я не надто зрозумів, було, якщо обробляти UnhandledException, я б спіймав також ThreadException - що, здається, не так
JohnIdol
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.