Wie gesamte Kette von Ausnahmen in Application.ThreadException Event-Handler zu bekommen?
Frage
Ich arbeite nur auf Ausnahmebehandlung in einem .NET 2.0 app Festsetzung, und ich stolperte auf einig seltsames Problem mit Application.ThreadException .
Was ich will, ist in der Lage sein, alle Ausnahmen von den Ereignissen hinter GUI-Elementen zu fangen (z Button_Click, etc.). Ich möchte dann diese Ausnahmen auf ‚Verhängnis‘ filtern, zum Beispiel hält mit einigen Arten von Ausnahmen sollte die Anwendung ausgeführt und mit anderen sollte es verlassen.
In einer anderen .NET 2.0 app Ich habe gelernt, dass standardmäßig nur im Debug-Modus tatsächlich die Ausnahmen ein Application.Run oder Application.DoEvents rufen lassen. Im Release-Modus geschieht dies nicht, und die Ausnahmen haben ‚gefangen‘ das Application.ThreadException Ereignis mit werden.
Nun aber ich bemerkte, dass das Ausnahmeobjekt in dem ThreadExceptionEventArgs des Application.ThreadException Ereignisses vergangen ist immer die innerste Ausnahme in der Ausnahmekette . Für die Protokollierung / Debugging / Design-Zwecke will ich wirklich die gesamte Kette von Ausnahmen though. Es ist nicht leicht zu bestimmen, welche externes System zum Beispiel schlug fehl, wenn Sie nur eine Socket Griff bekommen: wenn es wie zum Beispiel gewickelt ist ein NpgsqlException, dann zumindest wissen Sie, es ist ein Datenbankproblem.
So, wie auf die gesamte Kette von Ausnahmen von dieser Veranstaltung zu bekommen? Ist es überhaupt möglich, oder muß ich meine excepion in einer anderen Art und Weise der Handhabung gestalten?
Beachten Sie, dass ich -sort tun von- Abhilfe mit Application.SetUnhandledExceptionMode , aber dies bei weitem nicht ideal ist, weil ich muss meine eigene Nachrichtenschleife rollen.
EDIT: mehr Fehler zu vermeiden, die GetBaseException () -Methode nicht tut, was ich will : es gibt nur die innerste Ausnahme, während das einzige, was habe ich schon die innerste Ausnahme. Ich mag an der äußersten Ausnahme erhalten!
Lösung
Diese Frage ist mehr sinnvoll formuliert und beantwortet hier:
Andere Tipps
Ich habe versucht, dieses Verhalten zu reproduzieren (immer die innerste Ausnahme bekommen), Frankreich aber ich bekomme die Ausnahme, die ich erwarten, mit allen Innerexceptions intakt.
Hier ist der Code I-Test verwendet:
Private Shared Sub Test1()
Try
Test2()
Catch ex As Exception
Application.OnThreadException(New ApplicationException("test1", ex))
End Try
End Sub
Private Shared Sub Test2()
Try
Test3()
Catch ex As Exception
Throw New ApplicationException("test2", ex)
End Try
End Sub
Private Shared Sub Test3()
Throw New ApplicationException("blabla")
End Sub
Private Shared Sub HandleAppException(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)
...
End Sub
Unter HandleAppException Griffe Application.ThreadException. Die Test1 () -Methode aufgerufen zuerst.
Dies ist das Ergebnis (e As ThreadExceptionEventArgs) bekomme ich in HandleAppException:
Thread http://mediasensation.be/dump/?download=ThreadException.jpg
Wenn Sie nur Ausnahmen fangen und (Wieder-) werfen, wil keine Innerexceptions auftauchen, aber es wird auf die Ausnahme angehängt werden Stacktrace , wie folgt aus:.
bei SO.Test3 () in Test.vb: Linie 166
bei SO.Test2 () in Test.vb: Linie 159
bei SO.Test1 () in Test.vb: Linie 151
Normalerweise verlierst du nur die ganze Ausnahme Kette mit Ausnahme der Basis Ausnahme in einem Application.ThreadException Exception-Handler, wenn die Ausnahme in einem anderen Thread passiert ist.
Aus dem MSDN Library :
Mit diesem Ereignis können Sie Ihre Windows Forms Anwendung zu handhaben anders unbehandelte Ausnahmen, die auftreten, in Windows Forms Fäden. Bringen Sie Ihre Event-Handler zum Thread Ereignis mit diesen Ausnahmen zu behandeln, die verlassen wird Ihre Anwendung in ein unbekannter Zustand. Wo möglich, Ausnahmen sollten durch ein behandelt werden strukturierte Ausnahmebehandlung Block.
Lösung: Wenn Sie Einfädeln, stellen Sie sicher, dass alle Fäden / Asynchron-Anrufe in einem try / catch-Block sind. Oder wie Sie gesagt haben, können Sie mit Application.SetUnhandledExceptionMode spielen.
Nur etwas Interessantes entdeckt. Verschiedene GUI-Ereignisse werden Sie unterschiedliche Ergebnisse erhalten. Eine Ausnahme von einem Handler wird in Application.ThreadException Ereignisse Form.Shown geworfen führt die inner meisten Ausnahme abfangen, aber genau die gleiche Code läuft in der Form.Load Veranstaltung wird in dem Außen meist Exception immer in Application.ThreadException gefangen.
Haben Sie die Exception.GetBaseException Methode versucht? Dies gibt die Ausnahme, die die Application.TreadException erstellt. Sie könnten dann den gleichen Prozess verwenden, um die Kette zu gehen, um alle Ausnahmen zu bekommen.
Basierend auf einige der Informationen in dieser Kette, benutzen ich UnhandledExceptionMode.ThrowException zu UnhandledExceptionMode.CatchException gegenüber. Ich fange dann die Ausnahme außerhalb der Run Form () und das gibt mir die gesamte Kette von Ausnahmen.
Nach der MSDN-Dokumentation:
Wenn in einer abgeleiteten Klasse überschreibt, Exception zurück, die die Ursache für eine oder mehr nachfolgenden Ausnahmen ist.
Public Overridable Function GetBaseException() As Exception
Dim innerException As Exception = Me.InnerException
Dim exception2 As Exception = Me
Do While (Not innerException Is Nothing)
exception2 = innerException
innerException = innerException.InnerException
Loop
Return exception2
End Function
Sie können eine Variation dieses verwenden, um die Ausnahme Kette zu analysieren.
Public Sub LogExceptionChain(ByVal CurrentException As Exception)
Dim innerException As Exception = CurrentException.InnerException
Dim exception2 As Exception = CurrentException
Debug.Print(exception2.Message) 'Log the Exception
Do While (Not innerException Is Nothing)
exception2 = innerException
Debug.Print(exception2.Message) 'Log the Exception
'Move to the next exception
innerException = innerException.InnerException
Loop
End Sub
Das würde mich schlagen, wie genau das, was Sie suchen.