Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception handling behavior in WinForms application, which uses modal dialog

I've come across such a situation. WinForms application has two forms. The main form has a button, when user clicks it, modal dialog is shown. The dialog form has a button too, when user clicks it, exception is thrown.

Exception handling differs, when application running under debugger and running itself. Here's minimal code, reproducing this behavior:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            using (var dialog = new Form2())
            {
                dialog.ShowDialog();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Oops! " + ex.Message);
        }
    }
}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

When debugging, raising an exception closes the dialog, and exception handler in Form1.button1_Click handles exception.

When running application itself, raising an exception doesn't close the dialog. Instead of this, default Application.ThreadException handler being invoked.

Why (and what for) does the behavior differs? How to bring it into accord with each other?

like image 302
Dennis Avatar asked Apr 17 '12 08:04

Dennis


1 Answers

Try this in your Program.Main():

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
    Application.Run(new Form1());
}

The reason is to do with the way Windows Forms assemblies are run outside of the Visual Studio Hosting process. See this:

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx

If you set the above line of code to:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

And run it in VS, you will see what the default behaviour is - the dialog box to which you refer will be shown, once you step over the initial exception in code. The default is simply different depending on whether you run in hosted or standalone mode.

Well, the "Why" is kind of covered in the MS link - the error occurs in an event handler, which is on a different thread. The default behaviour is to treat this differently, under WinForms only. If you put this line after your call to the dialog:

throw new Exception("Bah!");

And keep the behaviour on CatchException you will see that it goes to your exception handler as you would expect. It's only the exception in the event handler which is processed differently. Hope that helps.

like image 101
Mel Padden Avatar answered Nov 12 '22 14:11

Mel Padden