Mint Source

Code snippets, tips, and tricks…

Posts Tagged ‘Exception

Handling Unhandled Exceptions in .NET 4.0

leave a comment »

When an exception is thrown, the stack is unwound until a catch block is encountered that accepts the thrown exception type or a base class of it.
If a suitable catch block isn’t found in the call stack, the exception is unhandled and the application terminates immediately with a Windows error message, control of the application is lost.

To regain control, one of the .NET unhandled exception events can be hooked. These allow the developer to save the state of the application, log the exception appropriately, provide custom feedback to the user, or sometimes, stop the application from terminating.

Three unhandled exception events applicable to WPF applications are described below.

The AppDomain.CurrentDomain.UnhandledException event is raised when the entire stack for a thread has been unwound without finding an applicable exception handler. Even when using this event to catch unhandled exceptions, the application process can still be forced to terminate. Therefore, it is best to ensure unhandled exceptions cannot be raised by background threads.

static App() // Static Constructor
{
    AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
}

static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
    // Log the exception, save state, etc.
}

The method below will trigger the UnhandledException event.

static void ThrowThreadException()
{
    ThreadPool.QueueUserWorkItem(_ =>
    {
        throw new ApplicationException("Exception thrown from within a separate Thread.");
    });
}

The TaskScheduler.UnobservedTaskException event is raised when an exception occurs within a Task and is not subsequently ‘observed’ before the task is disposed. If this event isn’t handled, or the UnobservedTaskExceptionEventArgs.SetObserved method isn’t called, the exception escalation policy is triggered which terminates the application by default.

static App() // Static Constructor
{
    TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionHandler;
}

static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs e)
{
    e.SetObserved(); // Stop the exception from escalating.
    // Log the exception, save state, etc.
}

The method below will trigger the UnobservedTaskException event. Garbage collection forces the unhandled exception to be thrown immediately for demonstration purposes.

static void ThrowTaskException()
{
    Task.Factory.StartNew(() =>
    {
        throw new ApplicationException("Exception thrown from within a Task.");
    });
    Thread.Sleep(500); // Ample time for the task to execute.
    GC.Collect(); // Force the task to be garbage collected.
}

The Application.DispatcherUnhandledException event is raised when an exception occurs within the UI thread but is not handled. If this event isn’t handled, or the DispatcherUnhandledExceptionEventArgs.Handled property isn’t set to true, the application is terminated.

protected override void OnStartup(StartupEventArgs e)
{
    DispatcherUnhandledException += DispatcherUnhandledExceptionHandler;
    base.OnStartup(e);
}

static void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    e.Handled = true; // Stop the exception from escalating.
    // Log the exception, save state, etc.
}

The method below will trigger the DispatcherUnhandledException event.

static void ThrowDispatcherException()
{
    throw new ApplicationException("Exception thrown from within the UI thread.");
}

Additional References
Design Guidelines for Exceptions
Handling and Throwing Exceptions

Written by Andy Lamb

April 4, 2012 at 22:22

Posted in .NET

Tagged with , , ,