Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception handling for events

I apologize if this is a simple question (my Google-Fu may be bad today).

Imagine this WinForms application, that has this type of design: Main application -> shows one dialog -> that 1st dialog can show another dialog. Both of the dialogs have OK/Cancel buttons (data entry).

I'm trying to figure out some type of global exception handling, along the lines of Application.ThreadException. What I mean is:

Each of the dialogs will have a few event handlers. The 2nd dialog may have:

private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    try
    {      
        AllSelectedIndexChangedCodeInThisFunction();
    }
    catch(Exception ex)
    {
        btnOK.enabled = false;  // Bad things, let's not let them save
        // log stuff, and other good things
    }
}

Really, all the event handlers in this dialog should be handled in this way. It's an exceptional-case, so I just want to log all the pertinent information, show a message, and disable the okay button for that dialog.

But, I want to avoid a try/catch in each event handler (if I could). A draw-back of all these try/catch's is this:

private void someFunction()
{
    // If an exception occurs in SelectedIndexChanged,
    // it doesn't propagate to this function
    combobox.selectedIndex = 3; 
}

I don't believe that Application.ThreadException is a solution, because I don't want the exception to fall all the way-back to the 1st dialog and then the main app. I don't want to close the app down, I just want to log it, display a message, and let them cancel out of the dialog. They can decide what to do from there (maybe go somewhere else in the app).

Basically, a "global handler" in between the 1st dialog and the 2nd (and then, I suppose, another "global handler" in between the main app and the 1st dialog).

like image 704
JustLooking Avatar asked Mar 26 '10 15:03

JustLooking


2 Answers

Yes, the default handling of Application.ThreadException was a mistake. Unfortunately, it was a necessary mistake, needed to not immediately discourage and despair hundreds of thousands of programmers writing their first Windows Forms application.

The fix you are contemplating is not a fix, it has a lot of potential to make it worse. While a user clicking the Continue button on the exception dialog is a questionable outcome, swallowing exceptions in a global exception handler is much worse.

Yes, do write a replacement handler for ThreadException. Have it display the value of e.Exception.ToString() in a message box so the user has some idea what blew up. Then fire off an email or append to an error log so you know what went wrong. Then call Environment.FailFast() so no more damage can be done.

Do the same for AppDomain.CurrentDomain.UnhandledException. It won't get much of a workout.

Use the feedback to improve your code. You'll find out where validation is required. You can help the customer's IT staff diagnose trouble with their LAN and equipment. And you'll find the very few cases where your own try/catch blocks might be able to recover from the exception.

like image 158
Hans Passant Avatar answered Sep 28 '22 06:09

Hans Passant


You may be able to use the AppDomain.CurrentDomain.UnhandledException handler to intercept the errors on the main UI thread and handle them per-dialog. From MSDN:

In applications that use Windows Forms, unhandled exceptions in the main application thread cause the Application.ThreadException event to be raised. If this event is handled, the default behavior is that the unhandled exception does not terminate the application, although the application is left in an unknown state. In that case, the UnhandledException event is not raised. This behavior can be changed by using the application configuration file, or by using the Application.SetUnhandledExceptionMode method to change the mode to UnhandledExceptionMode.ThrowException before the ThreadException event handler is hooked up. This applies only to the main application thread. The UnhandledException event is raised for unhandled exceptions thrown in other threads.

like image 33
LBushkin Avatar answered Sep 28 '22 08:09

LBushkin