Unhandled Exceptions

Unhandled exceptions are not handled directly in application code but deferred to a global handler. As the default behavior, the global handler reports the exception in an error box that presents a variety of choices. For applications running under the control of a debugger, the exception is usually trapped in the debugger.

What is the life cycle of an exception? Exceptions are initially categorized as first-chance exceptions. If the application is running under the auspices of a debugger, the debugger is first consulted about the exception. Debuggers typically ignore first-chance exceptions, and the exception is then forwarded to the application. When no debugger is present, the first-chance exception is immediately sent to the application. If the application does not handle the first-chance exception, the exception becomes a high-priority second-chance exception. If a debugger is attached, the second-chance exception typically is handled by the debugger. For example, upon finding a second-chance exception, the Visual Studio debugger transfers the user to the location in the source code where the exception occurred. This assumes that source code is available. If it is not, the user is shown a disassembly. If no debugger is present, execution is transferred to a global exception handler, which displays an error dialog box and then terminates the application. Figure 12-2 shows the life cycle of an exception.

The life cycle of an exception, which begins when an exception is raised

Figure 12-2. The life cycle of an exception, which begins when an exception is raised

Applications can trap unhandled exceptions. The mechanism is different between Microsoft Windows Forms and Console applications. For Windows Forms, add a handler to the Application.ThreadException event. For Console applications, the handler is added to the AppDomain.UnhandledException event. Methods added to the Application.ThreadException event chain catch and handle the exception. This is an advantage when compared with AppDomain.UnhandledException. Event handlers for the AppDomain.UnhandledException event can respond to an unhandled exception, but the exception is not caught. Therefore, the exception will resurface after the handlers have finished.

Do not use the unhandled exception handler to catch all exceptions. Proper application design identifies specific exceptions that an application should anticipate. Those exceptions should be caught and handled within the boundaries of structured exception handling. Reserve the unhandled exception method for unanticipated exceptions.

Application.ThreadException

In a Windows Forms application, an Application.ThreadException event is raised upon an unhandled exception. Subscribe to the ThreadException event to handle the unhandled exception. The subscriber is an exception handler, which prevents the application from being terminated. Do not propagate the trapped exception in the ThreadException exception handler. The new exception would be unprotected and will likely terminate the application. After the unhandled exception handler completes, execution simply continues.

Subscribe to the ThreadException event with a ThreadExceptionEventHandler delegate, which has two parameters. The object parameter is the thread object of the thread that raised the exception. The ThreadExceptionEventArg parameter of the System.Threading namespace contains the exception that was unhandled. This is the signature of the ThreadExceptionEventHandler:

void ThreadExceptionEventHandler(object sender,
    ThreadExceptionEventArgs e)

In the following code, the OnThreadException handler is added to the ThreadException event. The btnException_Click method raises an unhandled divide-by-zero exception. The unhandled exception is then handled in the OnThreadException method, which displays an informative message. Run the application in release mode for the expected results. Otherwise, the Visual Studio debugger intercepts the exception:

private void btnException_Click(object sender, EventArgs e) {
      int vara = 5, varb = 0;
      vara /= varb;
}

private void Form1_Load(object sender, EventArgs e) {
      Application.ThreadException += new
            System.Threading.ThreadExceptionEventHandler(
                OnThreadException);
}

void OnThreadException(object sender, ThreadExceptionEventArgs e) {
      Thread t = (Thread) sender;
      Exception threadexception = e.Exception;
      string errormessage = "Thread ID: " +
          t.ManagedThreadId.ToString() +
            " [ " + threadexception.Message + " ]";
      MessageBox.Show(errormessage);
}

AppDomain.UnhandledException

When an unhandled exception occurs in a Console application, the AppDomain.UnhandledException event is raised. Subscribe to this event to clean up the resources of the application, with actions such as closing files and relinquishing data connections. You also might record the unhandled exception in the event log or other location. It is important to note that the exception is not caught in the AppDomain.UnhandledException handler. When the handler is completed, the unhandled exception will cause the application to be terminated. The AppDomain.UnhandledException event is triggered only in the starting application domain of the program.

Subscribe to the AppDomain.UnhandledException event with an UnhandledExceptionEventHandler delegate. The delegate has two parameters. The object parameter is the originating AppDomain. The UnhandledExceptionEventArgs parameter contains the specifics of the unhandled exception. This is the signature of the UnhandledExceptionEventHandler:

void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e)

UnhandledExceptionEventArgs offers the IsTerminating and ExceptionObject properties. IsTerminating is a Boolean property indicating the status of the application. If true, the application is terminating because of the exception. If false, the application can survive the exception. This property is always true. Unhandled exceptions on both managed and unmanaged threads terminate an application. This is cleaner than the previous unhandled exception model, where exceptions raised on managed threads were nonfatal. The ExceptionObject property is the exception object for the unhandled exception. Inexplicably, this property is an object type, not an exception type. Cast the property to the exception type to access the details of the exception.

In the following Console application, the OnUnhandledException method is added to the AppDomain.UnhandledException event. When the subsequent divide-by-zero exception occurs, the OnUnhandledException method is called:

using System;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            AppDomain.CurrentDomain.UnhandledException +=
                new UnhandledExceptionEventHandler(
                    OnUnhandledException);

            int vara = 5, varb = 0;
            vara /= varb;
        }

        public static void OnUnhandledException(
                object sender, UnhandledExceptionEventArgs e) {
            Exception except=(Exception) e.ExceptionObject;

            string errormessage = "Application has failed" +
                " [ Exception " + except.Message + " ]";
            Console.WriteLine(errormessage);
        }
    }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.51.246