2009-08-19 6 views
6

Dies steht in Beziehung zu einer previous question.Warum beenden AppDomain-Ausnahmen die Anwendung ausnahmslos?

Was ich jetzt zu verstehen versuche ist, wie verhindert werden kann, dass UI-Thread-Ausnahmen die Anwendung beenden können, während Nicht-UI-Ausnahmen nicht sein können.

Als Referenz siehe this example.

Am wichtigsten ist, was ich in diesem Fall tun könnte, ist "still" den Prozess zu beenden - ohne die Windows-Dialogbox anzuzeigen, die fragt, ob ich einen Fehlerbericht senden möchte oder nicht.

Das ist mein AppDomain UnhandledExceptionHandler:

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{    
    try 
    { 
     // Maybe do some logging here if allowed 
    } 
    catch 
    { 
    } 

    // then just terminate the application 
    Application.Exit();    
} 

UPDATE
Im Lichte der Kommentare in this answer, würde ich, dass vor allem zu klären, wie ich mehr über den Mechanismus finden, möchte darauf, dass ermöglicht dem UI-Thread eine frühe Möglichkeit, nicht behandelte Ausnahmen über den Application.ThreadException-Mechanismus abzufangen. Und ob ein solches Verhalten in einem Nicht-UI-Thread implementiert werden könnte.

Antwort

7

So, nach ein paar mehr Suchanfragen bei Google zu tun fand ich diese sehr interessante Erklärung, die das gleiche Problem von Jeff Atwood on his blog wie beschrieben gegeben wurde.

Hallo alle, Sorry für die Verwirrung. Dieses Verhalten ist eigentlich das Design, obwohl das Design manchmal etwas verworren sein kann.

Die erste Sache zu verstehen ist, dass das UnhandledException-Ereignis kein unbehandeltes Ausnahme "Handler" ist. Registrierung für das Ereignis, im Gegensatz zu dem, was die Dokumentation sagt :-(, verursacht keine unbehandelten Ausnahmen zu behandeln. (Seitdem würden sie nicht unbehandelt sein, aber ich werde mit dem Zirkelschluss bereits aufhören ...) Das UnhandledException Ereignis einfach Sie darüber informiert, dass eine Ausnahme unhandled gegangen ist, falls Sie versuchen wollen stirbt Zustand vor dem Thread oder Anwendung zu speichern. FWIW, ich habe einen Fehler reicht die docs behoben.

Gerade kompliziere die Dinge, in v1.0 und 1.1, eine unbehandelte Ausnahme bedeutete nicht immer, dass Ihre Anwendung sterben würde. Wenn die nicht behandelte Ausnahme in einem anderen Fall als dem Hauptthread oder einem Thread aufgetreten ist, der sein Leben in nicht verwaltetem Code begonnen hat, hat die CLR die Ausnahme abgefangen und Ihre App weiter ausgeführt. Das war im Allgemeinen böse, denn was häufig passieren würde, war zum Beispiel, dass ThreadPool-Threads nacheinander still abstirbten, bis Ihre Anwendung keine Arbeit mehr tat. Die Ursache für diese Art von Versagen herauszufinden, war nahezu unmöglich. Das könnte der Grund sein, warum Jeff dachte, dass es vorher funktioniert hat ... er sah immer nur Abstürze auf Nicht-Haupt-Threads.

In Version 2.0 wird eine nicht behandelte Ausnahme in einem Thread die Anwendung herunterfahren. Wir haben festgestellt, dass das Debuggen von Abstürzen wesentlich einfacher ist als das Debuggen von Abstürzen oder das oben beschriebene Problem des automatischen Stillstands.

BTW, auf meinem 1.1-Rechner hat das Beispiel von MSDN die erwartete Ausgabe; Es ist nur so, dass die zweite Zeile erst angezeigt wird, nachdem Sie einen Debugger angehängt haben (oder nicht). In v2 haben wir Dinge umgedreht, so dass das UnhandledException-Ereignis ausgelöst wird, bevor der Debugger anlegt, was die meisten Leute erwarten.

Jonathan Keljo CLR Ausnahmen PM Jonathan Keljo am 18. Februar 2005 22.02

Allerdings bin ich immer noch daran interessiert, wie die UI-Thread erreicht den Trick ermöglicht es Ihnen, einen Haken haben -aller Handler für alle UI-Thread-Ausnahmen.

Noch mehr, Ich bin in eine Art und Weise sehr daran interessiert, den .NET JIT-Debugging Dialog für meine Anwendung nur (ohne disabling it for the whole machine as seen here)

3

Es ist nicht so, dass eine AppDomain-Ausnahme die Anwendung beendet, es ist, dass nicht behandelte Ausnahmen (jeder Art) die AppDomain abreißen und die Anwendung beenden.

Das Problem hier ist, dass Sie UI-Thread-Ausnahmen explizit behandeln können, auf einer ziemlich hohen Ebene. Wenn Sie jedoch eine nicht behandelte Ausnahme in einem Hintergrund-Thread haben, gibt es keine Möglichkeit, sie auf der gleichen Ebene leicht zu behandeln, sodass sie sich tendenziell ausbreitet und die Anwendung herunterzieht. Application.ThreadException können Sie zumindest wissen, dass dies der Grund für den Fehler ist, und es bei Bedarf protokollieren.

Nicht behandelte Ausnahmen im UI-Thread führen dazu, dass dasselbe passiert.

+0

@Reed zu deaktivieren: „Unbehandelte Ausnahmen in dem UI-Thread das gleiche verursachen etwas passieren. " - das ist nicht wahr. Bitte erstellen Sie eine Testanwendung und probieren Sie es selbst aus. –

+1

Technisch hätte ich "Unhandled Exceptions auf dem Hauptthread" sagen sollen. Windows Forms fügt ein eigenes Verhalten zur Ausnahmebehandlung für den Benutzeroberflächenthread hinzu (da es vollständig im Benutzeroberflächenthread ausgeführt wird), der das Verhalten des Hauptthreads ändert. Machen Sie eine Konsolenanwendung, und versuchen Sie dies, und Sie werden sehen, dass es egal ist, auf welchem ​​Thread Dinge vorkommen - sie werden alle die Anwendung abreißen. –

+0

Dann sollte ich meine Frage neu formulieren: Wie erreicht der UI-Thread das allgemeine Ausnahmebehandlungsverhalten? Ist das etwas, das ich als Verhalten für einen Nicht-UI-Thread replizieren könnte? –

2

Hilft das überhaupt?

Improved Unhandled Exception behavior in .NET 2.0

Auch scheint dieser Code zu "leise sterben". Suchst du nach etwas anderem?

using System; 

namespace UnhandledException 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; 

      throw new NotImplementedException(); 
     } 

     static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) 
     { 
      Exception exception = (Exception)e.ExceptionObject; 
      System.Console.WriteLine("exception=[" + exception.ToString() + "]"); 

      Environment.Exit(-1); 
     } 
    } 
} 
+0

Ja tut es .. Ich hatte gerade den Beitrag und Kommentare gelesen, als Sie das gepostet haben. +1 aber .. –

+0

Ja, Environemnt.Exit scheint den Trick zu tun! Ich lasse die Fragen noch eine Weile offen, um zu sehen, ob irgendjemand einen Einblick geben kann, wie der UI-Thread die Catch-All-Ausnahme durchführt. Sonst hast du meine Stimme für die angenommene Antwort! –

+0

Application.ThreadException ist nur eine weitere Variante eines "unhandled Exception Handlers". Es gibt viele Varianten (Console App vs. WinForms vs. WebForms vs. WCF usw.). Ich bin mir nicht sicher, ob ich deine Frage verstehe. Im Allgemeinen implementiere ich jeden, der anwendbar ist. –

Verwandte Themen