|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
InnerException > BackgroundWorker > MyApplication.UnhandledExceptihandler behaves differently when the exception originates from the background thread of a BackgroundWorker component. e.g. The event handler displays the message from the exception and from the inner exception: Partial Friend Class MyApplication Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException If e.Exception.InnerException Is Nothing Then MsgBox(e.Exception.Message & " Nothing") Else MsgBox(e.Exception.Message & " " & e.Exception.InnerException.Message) End If e.ExitApplication = False End Sub End Class The following code behaves as expected, the event handler displaying “Blah Fooâ€. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try Throw New Exception("Foo") Catch ex As Exception Throw New Exception("Blah", ex) End Try End Sub But the following code behaves unexpectedly, the event handler displaying “Foo Nothingâ€, which, I guess, comes as a result of the base exception being passed to the event handler. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.BackgroundWorker1.RunWorkerAsync() End Sub Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork Try Throw New Exception("Foo") Catch ex As Exception Throw New Exception("Blah", ex) End Try End Sub Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted Throw e.Error End Sub I’d appreciate an explanation as to why and also an indication as to how I can get the complete exception tree. Hi Dick,
Yes, I can reproduce the problem with the code snippet you provided. Below is my detailed analysis process for this problem, for your information: VB2005 MyApplication.UnhandledException internally leverages Application.ThreadException to implement the magic, I have proved this in the link below: http://groups.google.com/group/microsoft.public.dotnet.framework.windowsform s/msg/5422486e68eddae7?hl=zh-CN& So I tried to disable "Application Framework" in my testing VB2005 project and used Application.ThreadException directly to handle this exceptoin, like this: Public Class Form1 <STAThread()> _ Shared Sub Main() AddHandler Application.ThreadException, AddressOf OnThreadException Application.Run(New Form1()) End Sub Public Shared Sub OnThreadException(ByVal sender As Object, ByVal t As ThreadExceptionEventArgs) If t.Exception.InnerException Is Nothing Then MsgBox(t.Exception.Message & " Nothing") Else MsgBox(t.Exception.Message & " " & t.Exception.InnerException.Message) End If End Sub .... End Class Oh, I find the problem still exist, Application.ThreadException will also only report the inner-most exception "Foo". However, if we catch the exception in BackgroundWorker1_RunWorkerCompleted with code snippet below, we will get the 2 exceptions without any problem: Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted Try Throw e.Error Catch ex As Exception If ex.InnerException Is Nothing Then MsgBox(ex.Message & " Nothing") Else MsgBox(ex.Message & " " & ex.InnerException.Message) End If End Try End Sub This reveals that there is some magic happen during the unwinding of the stack for exception. By comparing the call stack of BackgroundWorker1_RunWorkerCompleted() method and OnThreadException() method, I find that the exception handling unwinding stops at "System.Windows.Forms.Control.InvokeMarshaledCallbacks" internal method. Then I launched Reflector to examine "System.Windows.Forms.Control.InvokeMarshaledCallbacks" source code. My eyes stop on the following code snippet: Private Sub InvokeMarshaledCallbacks() ..... Try If (NativeWindow.WndProcShouldBeDebuggable AndAlso Not entry1.synchronous) Then Me.InvokeMarshaledCallback(entry1) Else Try Me.InvokeMarshaledCallback(entry1) Catch exception1 As Exception entry1.exception = exception1.GetBaseException End Try End If Finally entry1.Complete If ((Not NativeWindow.WndProcShouldBeDebuggable AndAlso (Not entry1.exception Is Nothing)) AndAlso Not entry1.synchronous) Then Application.OnThreadException(entry1.exception) End If End Try ..... End Sub Yes, InvokeMarshaledCallbacks() method catches the exception we throw and then calls "exception1.GetBaseException" method to get the inner-most exception object and pass it to the Application.OnThreadException() method. We finally find the root cause now! Then I want to understand why Winform InvokeMarshaledCallbacks() method will translate the exception into inner-most exception(Foo) for Application.OnThreadException() method. I performed some search in our internal database with one existing record regarding our problem. Based on the winform comfirmation in the record, our analysis is correct of the root cause and this behavior is intended. The reason was to prevent the user from seeing too much of the Windows.Forms internal mechanisms. This is because the winform's default error dialog also leverages Application.ThreadException to show the exception details. .Net Winform team trims the other exceptions information so that the default error dialog will not display all the details to the end user. Also, some MSFTs have sugguested to change this behavior. However, .Net Winform team thinks that changing the exception to throw is a breaking change and for this reason WinForms will keep sending the innermost exception to the Application.ThreadException handler. Hope this helps. Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. |
|||||||||||||||||||||||