Was ist der Unterschied zwischen Application.ThreadException und AppDomain.CurrentDomain.UnhandledException?

107

Okay, das ist einfach:

  • Was ist der Unterschied zwischen Application.ThreadExceptionund
    AppDomain.CurrentDomain.UnhandledException?

  • Muss ich mit beiden umgehen?

Vielen Dank!

JohnIdol
quelle

Antworten:

98

Application.ThreadException ist spezifisch für Windows Forms. Winforms führt Ereignishandler als Antwort auf von Windows an Winforms gesendete Nachrichten aus. Das Click-Ereignis zum Beispiel, ich bin sicher, dass Sie sie kennen. Wenn ein solcher Ereignishandler eine Ausnahme auslöst, gibt es in der Winforms-Nachrichtenschleife einen Back-Stop, der diese Ausnahme abfängt.

Dieser Backstop löst das Application.ThreadException- Ereignis aus. Wenn Sie es nicht überschreiben, erhält der Benutzer einen ThreadExceptionDialog . Dadurch kann er die Ausnahme ignorieren und Ihr Programm weiter ausführen. Übrigens keine gute Idee.

Sie können dieses Verhalten deaktivieren, indem Sie Application.SetUnhandledExceptionMode () in der Main () -Methode in Program.cs aufrufen . Ohne diesen Backstop geschieht das Übliche, wenn ein Thread aufgrund einer nicht behandelten Ausnahme stirbt: AppDomain.UnhandledException wird ausgelöst und das Programm wird beendet.

Fwiw: "ThreadException" war eine sehr schlechte Namenswahl. Es hat nichts mit Threads zu tun.

Hans Passant
quelle
Und wie Sie verhindern können, dass die WinForms-Anwendung beim Auftreten von abstürzt Application.ThreadException. Ich habe hier [mit ] meinem kleinen C # -Code eine Frage dazu gestellt .
Mahesha999
2
Ich habe es immer als Application-Thread-Ausnahme gelesen, da Winforms an einen einzelnen Thread gebunden ist.
Gusdor
36

Aus der Quelle :

In Anwendungen, die Windows Forms verwenden, führen nicht behandelte Ausnahmen im Hauptanwendungsthread dazu, dass das Application.ThreadException Ereignis ausgelöst wird . Wenn dieses Ereignis behandelt wird, ist das Standardverhalten, dass die nicht behandelte Ausnahme die Anwendung nicht beendet, obwohl die Anwendung in einem unbekannten Zustand belassen wird. In diesem Fall wird das UnhandledException Ereignis nicht ausgelöst. Dieses Verhalten kann mithilfe der Anwendungskonfigurationsdatei oder mithilfe der Application.SetUnhandledExceptionModeMethode zum Ändern des Modus UnhandledExceptionMode.ThrowExceptionvor dem Anschließen des ThreadException Ereignishandlers geändert werden. Dies gilt nur für den Hauptanwendungsthread. Das UnhandledException Ereignis wird für nicht behandelte Ausnahmen ausgelöst, die in anderen Threads ausgelöst werden.

Ab Visual Studio 2005 bietet das Visual Basic- Anwendungsframework ein weiteres Ereignis für nicht behandelte Ausnahmen im Hauptanwendungsthread - WindowsFormsApplicationBase.UnhandledException. Dieses Ereignis verfügt über ein Ereignisargumentobjekt mit demselben Namen wie das von AppDomain.UnhandledException verwendete Ereignisargumentobjekt, jedoch mit unterschiedlichen Eigenschaften. Insbesondere verfügt dieses Ereignisargumentobjekt über eine ExitApplicationEigenschaft, mit der die Anwendung weiter ausgeführt werden kann, wobei die nicht behandelte Ausnahme ignoriert wird (und die Anwendung in einem unbekannten Zustand belassen wird). In diesem Fall wird das Ereignis AppDomain.UnhandledException nicht ausgelöst.

Application.ThreadExceptionkann abgefangen werden und die Anwendung könnte fortgesetzt werden (im Allgemeinen ist dies keine gute Idee, aber für die Anwendung, die regelmäßig einige Aktionen ausführt, ist dies eine gute Lösung).

Verwenden Sie die Option zum Abfangen von Ausnahmen, die in Threads auftreten, die nicht von Windows Forms erstellt wurden und deren Eigentümer Windows Forms ist AppDomain.UnhandledException. Es ermöglicht der Anwendung, Informationen über die Ausnahme zu protokollieren, bevor der Systemstandardhandler die Ausnahme an den Benutzer meldet und die Anwendung beendet.
Die Behandlung dieser Ausnahme verhindert nicht, dass die Anwendung beendet wird.
Das Maximum, das getan werden kann (Programmdaten können beschädigt werden, wenn Ausnahmen nicht behandelt werden), ist das Speichern von Programmdaten für eine spätere Wiederherstellung. Danach wird die Anwendungsdomäne entladen und die Anwendung beendet.

Ab .NET 4 wird dieses Ereignis nicht für Ausnahmen ausgelöst, die den Status des Prozesses beschädigen, z. B. Stapelüberläufe oder Zugriffsverletzungen, es sei denn, der Ereignishandler ist sicherheitskritisch und verfügt über das HandleProcessCorruptedStateExceptionsAttribute Attribut.

Weitere Informationen finden Sie unter MSDN .

Serhio
quelle
18

OK - ich hatte es vor mir, dieser Code von msdn ist ziemlich selbsterklärend:

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
quelle
3
Dies steht im Gegensatz zu der anderen Antwort von serhio, wenn er sagt: UnhandledExceptionMode.ThrowException sollte festgelegt werden, bevor der ThreadException-Ereignishandler angeschlossen wird. Ich bin mir nicht sicher, ob die Reihenfolge wirklich wichtig ist ...
Davide Piras
@ DavidPiras ja, und es gibt etwas trüberes. SetUnhandledException scheint in meinem Fall keinen Unterschied zu machen.
Nawfal
0

Nun, die Sache ist, ThreadExceptiontritt aufgrund eines Problems mit Ihrem Thread auf, das Unhandled Exceptionausgelöst wird, wenn Sie Code eine Ausnahme auslösen, die nicht behandelt wird.

Der einfachste Weg, den zweiten zu verursachen, besteht darin, eine App ohne Versuch zu erstellen ... Blöcke zu fangen und eine Ausnahme auszulösen.

Wenn Sie jetzt eine Versicherung benötigen, können Sie beide behandeln. Wenn Sie jedoch Ihre exceptionsDaten erfassen und korrekt behandeln, sollten Sie den UnhandledExceptionHandler nicht benötigen, da er wie ein Fang für alle ist.

Joshua Cauble
quelle
danke - was mir nicht so klar war, war, wenn ich mit UnhandledException umgehen würde, würde ich auch ThreadException abfangen - was anscheinend nicht der Fall ist
JohnIdol