We help IT Professionals succeed at work.

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

FalconUK asked
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?
Watch Question

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



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
        End Using
    End Sub

    Private Sub DoWork()
        Throw New Exception
    End Sub

    Private Sub CallBack(ByVal iar As System.IAsyncResult)
            Dim ar As Runtime.Remoting.Messaging.AsyncResult = CType(iar, Runtime.Remoting.Messaging.AsyncResult)
            Dim d As DoWorkDel = CType(ar.AsyncDelegate, DoWorkDel)
        Catch ex As Exception
        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.

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.....



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 **************
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
    Assembly Version:
    Win32 Version:
    CodeBase: file:///C:/Documents%20and%20Settings/chris_browne/My%20Documents/Visual%20Studio%202005/Projects/ExpertsExchangeAsyncTest/ExpertsExchangeAsyncTest/bin/Debug/ExpertsExchangeAsyncTest.exe
    Assembly Version:
    Win32 Version: 8.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/Microsoft.VisualBasic/
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/
    Assembly Version:
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Runtime.Remoting/

************** 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

For example:

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

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.

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      


    Dim frm As Form2 = New Form2

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

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



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



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


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).

This one is on us!
(Get your first solution completely free - no credit card required)
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.


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.