We help IT Professionals succeed at work.

Dodgy WinForms Exception Handling When Using Asynchronous Delegates (VB.Net 2005)

FalconUK
FalconUK asked
on
579 Views
Last Modified: 2010-05-18
I've got a problem with exceptions being not handled correctly when showing a form from within a thread created when using a delegates BeginInvoke.

I.e. BeginInvoke runs a method async'ly which creates and shows a WinForm. And when this form throws an Exception I get a User-unhandled Exception thrown. In the VS2005 IDE this isn't so bad as it lets you continue, but once you run the application standalone you get a Unhandled Exception dialog and Details/Continue/Quit buttons.

Not really what you want.

I was under the impression that Exceptions thrown from within methods run in this manor would be propagated back out to the main thread when the call to EndInvoke was made, in my case from with in a callback method specified when calling BeginInvoke.

However, if, from within my asynchronous method, I choose not to open the form that throws the exception, and just to 'Throw New Exception' from right inside the method, this get handled correctly in my catch block when I call EndInvoke from within my call back method.

It seams that the exceptions are not handled correctly when they are thrown from within a form that was created within an asynchronous method when using asynchronous delegates.

How can I get these exceptions handled correctly?
Comment
Watch Question

maybe if you post the code it would be so much easier to understand what you are writing about.
cheers
NY

Author

Commented:
Okay...

So it's two forms, Form1 with two buttons and Form2 with one button.
Click the first button of Form1 to show Form2, then click the only button on Form2 to see it fall over.
Click the second button on Form1 to see it handle the exception correctly.

Important: Compile it and run it out side the VS IDE to see it really fail rather than breaking in code at the point of the un-handled exception.

Form1 code:

Imports System
Public Class Form1
    Private Delegate Sub DoWorkDel()

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim d As New DoWorkDel(AddressOf DoFormWork)
        d.BeginInvoke(New AsyncCallback(AddressOf CallBack), Nothing)
    End Sub
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim d As New DoWorkDel(AddressOf DoWork)
        d.BeginInvoke(New AsyncCallback(AddressOf CallBack), Nothing)
    End Sub

    Private Sub DoFormWork()
        Using f As New Form2
            f.ShowDialog()
        End Using
    End Sub

    Private Sub DoWork()
        Throw New Exception
    End Sub

    Private Sub CallBack(ByVal iar As System.IAsyncResult)
        Try
            Dim ar As Runtime.Remoting.Messaging.AsyncResult = CType(iar, Runtime.Remoting.Messaging.AsyncResult)
            Dim d As DoWorkDel = CType(ar.AsyncDelegate, DoWorkDel)
            d.EndInvoke(iar)
        Catch ex As Exception
            Windows.Forms.MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class


Form2 code:

Public Class Form2
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Throw New System.Exception("BANG")
    End Sub
End Class


I hope you can help, this is getting rather urgent, and I'm sure its just something that I don't yet fully understand about the way in which Exceptions are handled in worker threads in WinForms.

Cheers.
this may sound weird to you, but i compiled what you gave me, and i dont get any errors at all. every button i click works as expected.....

NY

Author

Commented:
Whats happening to mine then? Have I got things set up differently on my development computer to yours? If so what could it be?

I've just created a new project and copied in all that code I gave above, saved it, compiled it, shut down VS, and run the app from Explorer. When I click button1 to show Form2, then click button1 on Form2 I get an Unhandled Exception dialog with Details/Continue/Quit buttons. I would expect that the CallBack routine would have handled this exception? As it does with button1 on Form1.

Continue allows me to return to the application.
Quit shuts down the entire application.
And Details shows the following information:

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.Exception: BANG
   at WindowsApplication1.Form2.Button1_Click(Object sender, EventArgs e) in C:\Documents and Settings\chris_browne\My Documents\Visual Studio 2005\Projects\ExpertsExchangeAsyncTest\ExpertsExchangeAsyncTest\Form2.vb:line 3
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
ExpertsExchangeAsyncTest
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///C:/Documents%20and%20Settings/chris_browne/My%20Documents/Visual%20Studio%202005/Projects/ExpertsExchangeAsyncTest/ExpertsExchangeAsyncTest/bin/Debug/ExpertsExchangeAsyncTest.exe
----------------------------------------
Microsoft.VisualBasic
    Assembly Version: 8.0.0.0
    Win32 Version: 8.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/Microsoft.VisualBasic/8.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualBasic.dll
----------------------------------------
System
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Windows.Forms
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Configuration
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Xml
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
System.Runtime.Remoting
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Runtime.Remoting/2.0.0.0__b77a5c561934e089/System.Runtime.Remoting.dll
----------------------------------------

************** JIT Debugging **************
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.

For example:

<configuration>
    <system.windows.forms jitDebugging="true" />
</configuration>

When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.


???
Chris.
im not sure what you are trying to accomplish here. the thing works as you programmed it, i mean, when you put Throw New Exception, it will do just that, no wonder you are getting an exception when you run! but anyways, i think that you are trying to have something like form2 opened while form1 reports on the status of that?
in any case, not knowing a lot about delegates (am looking for such a great link a had but lost when i changed computers...) i dont think i could help any further for the moment.

*************
just a few things I googled up: (http://www.vbdotnetheaven.com/UploadFile/thiagu304/passdata12262006073406AM/passdata.aspx)

The Delegates Approach

 

Technically, a delegate is a reference type used to encapsulate a method with a specific signature and return type. You can encapsulate any matching method in that delegate. Here we are going to create a delegate with some signature and assign a function to the delegate to assign the text from textbox to label.

 

Follow the below steps:

 

Step 1: Add a delegate signature to form1 as below  

 

Public Delegate Sub delPassData(ByVal text As TextBox)

 

Step 2: In form1's button click event handler instantiate form2 class and delegate. Assign a function in form2 to the delegate and call the delegate as below  

 

Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles      

    btnSend.Click

    Dim frm As Form2 = New Form2

    Dim del As delPassData = New delPassData(AddressOf frm.funData)

    'Dim del As delPassData = New delPassData(frm.funData)

    del(Me.textBox1)

    frm.Show()

End Sub

 

Step 3: In form2, add a function to which the delegate should point to. This function will assign textbox's text to the label.  

 

Public Sub funData(ByVal text As TextBox)

    label1.Text = text.Text

End Sub


***********************

Author

Commented:
After an afternoon scratching my head and searching all over the internet I found this article:

http://support.microsoft.com/default.aspx/kb/324653/en-us

This explains why I'm seeing this behaviour, its nothing to do with the way in which I'm using asynchronous delegates, its to do with the way in which the message pump for each form is wrapped in an exception handler and the way in which it handles unhandled exceptions (that was a mouth full).

Chris.
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.