Unhandled exceptions in Windows Form events are not propagated up call stack

This article was previously published under Q324653
Unhandled exceptions that occur in Windows Form events are not propagated up the call stack to a structured exception handler in the calling procedure.
The Microsoft .NET Framework wraps the message pump in an exception handler. The .NET Framework only handles exceptions that reach the message pump and that the application has not already handled. Therefore, any unhandled exception that reaches the message pump is not propagated up the call stack.
To resolve this problem, create an exception handler for your unhandled exceptions by calling the Application.AddOnThreadException method and by passing the Application.ThreadException method a reference to a method in your application. This method is then called for any unhandled exceptions that occur on that thread. The OnThreadException event is raised when the Windows Forms window procedure receives an exception.

The following steps and sample code demonstrate how to use the Application.AddOnThreadException method to handle these exceptions.

Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements.
  1. Repeat steps 1 through 7 in the "Steps to Reproduce the Behavior" section.
  2. View the code for the Form1 class.
  3. Expand the Windows Form Designer generated code region.
  4. Replace the Sub New() constructor with the following code:
    Public Sub New()   MyBase.New()   'This call is required by the Windows Form Designer.   InitializeComponent()   'Add any initialization after the InitializeComponent() call.   'Explicitly set apartment state to single-threaded apartment (STA).   System.Threading.Thread.CurrentThread.ApartmentState = System.Threading.ApartmentState.STA   Dim eh As New ExceptionHandler()   AddHandler Application.ThreadException, AddressOf eh.OnThreadExceptionEnd Sub					
  5. On the Project menu, click Add Class.
  6. In the Name box, type ExceptionHandler.vb, and then click Open.
  7. Replace the code in the new ExceptionHandler class with the following code:
    Friend Class ExceptionHandler    Public Sub OnThreadException(ByVal Sender As Object, ByVal e As System.Threading.ThreadExceptionEventArgs)        'Add custom exception handling code here.        MessageBox.Show("Handled the following exception:" & _            vbCrLf & vbCrLf & e.Exception.Message)    End SubEnd Class					
  8. On the Debug menu, click Start Without Debugging.
  9. Click the command button. Notice that you receive the following message:
    Handled the following exception:

    My Exception
This behavior is by design.

Steps to Reproduce the Behavior

  1. Follow these steps to create a new Windows Application project in Visual Basic .NET:
    1. Start Microsoft Visual Studio .NET.
    2. On the File menu, point to New, and then click Project.
    3. In the New Project dialog box, click Visual Basic Projects under Project Types, and then click Windows Application under Templates. By default, Form1 is created.
  2. Drag a Button control from the toolbox to Form1.
  3. On the View menu, click Code to view the form class module.
  4. Add the following code to the Button1_Click event handler:
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click   Dim f As New Form2()   Try      f.Show()   Catch exc As Exception      MessageBox.Show(exc.Message)   Finally      f.Close()   End TryEnd Sub					
  5. On the Project menu, click Add Windows Form. Click OK to accept the default name (Form2) for the new form.
  6. On the View menu, click Code.
  7. Add the following code to the Form2_Load event handler:
    Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load   Throw New System.Exception("My Exception")End Sub					
  8. On the Debug menu, click Start Without Debugging.
  9. Click the command button. Notice that you receive the following error message:
    An unhandled exception has occurred in your application. If you Continue, the application will ignore this error and attempt to continue. If you click Quit, the application will be shut down immediately.

    My Exception.
This behavior appears to be incorrect because there is a structured exception handler in the calling procedure in Form1. However, because the call stack contains a message pump, the exception is not propagated up the call stack, and the exception handler in Form1 does not handle the exception. If you start the application with the debugger attached, the exception is handled. When the debugger is attached to the process, the exception is handled correctly because there are two message pumps that alllow the message to propagate up the callstack.

Article ID: 324653 - Last Review: 05/09/2008 21:54:19 - Revision: 6.0

Microsoft .NET Framework 1.1, Microsoft .NET Framework 1.0, Microsoft .NET Framework 2.0, Microsoft .NET Framework 3.0, Microsoft .NET Framework 3.5

  • kbnetframe100presp3fix kbprb KB324653