Order in Chaos: Handling unhandled exceptions in a WPF application

28 באוגוסט 2011

6 תגובות

Introduction

So you want to handle somehow all the unhandled exceptions in your application.
Usually you want to accomplish one of the following:

  • Log the exception for later diagnostics
  • Present the user an unhandled exception UI, nicer than the default

You heard there’s an event you should register, or maybe you find one by mistake, but is it the correct one?

Did you know there are four (!) different events for handling unhandled exceptions in the .NET framework?

So what is the difference between them and when should we use each one?
This post will hopefully answer these questions.

Note: this is NOT a replacement for try-catch blocks!

 

Summary

I’ll begin with the summary to avoid boring busy developers.

In a typical WPF application you should use Application.Current.DispatcherUnhandledException for exceptions generated on the UI thread and AppDomain.CurrentDomain.UnhandledException for all the other exceptions.

Now, for the details..

 

System.Windows.Forms.Application.ThreadException

This event is used for catching unhandled exceptions only on UI threads created by WinForms. Other exceptions, generated on non-UI threads won’t arrive to this event. Use AppDomain.Current.UnhandledException to catch them.

The default behavior of a WinForms application with an unhandled exception is to present the following error dialog:

image

If you register to this event, the application will not show the error dialog and will automatically extend the application life (i.e. the application won’t be killed).

If you do want to end your application, maybe after logging the exception or asking the user with a personalized dialog, you must do it yourself using Application.Exit().

You can find the MSDN documentation on this event here.

 

System.Windows.Application.Current.DispatcherUnhandledException

This event is used for catching unhandled exceptions only from the main UI thread created by WPF.

The default behavior of a WPF application with an unhandled exception is to present the following error dialog and end the application:

image

If you register to this event, you will get the chance to log the exception, but the application will still end, unless you set e.Handled = true, on the event’s EventArgs parameter.

You can find the MSDN documentation on this event here.

 

Dispatcher.UnhandledException

This event is used for catching unhandled exceptions on the thread attached to the specific Dispatcher (WPF only). Note, that in WPF two threads can have two different Dispatcher object attached. This event is only useful if you have several UI threads in your WPF application, which is quite rare. If you’re not sure, you probably need to handle only the previous event: Application.Current.DispatcherUnhandledException.

As in the previous event, if you register, you will get the change to log the exception. To prevent the exception internal handling from being called set e.Handled = true.

You can find the MSDN documentation on this event here.

 

AppDomain.CurrentDomain.UnhandledException

This event is used for catching unhandled exceptions generated from all threads running under the context of a specific application domain.

You can find the MSDN documentation on this event here.

 

Bonus: AppDomain.CurrentDomain.FirstChanceException

This event which exists only from .NET 4, is raised on ANY exception, if the handled one. In fact, the event is raised before the search for the catch blocks. You can’t handle the exception using this event. You can use it if you need to log exceptions that are caught.

You can find the MSDN documentation on this event here.

 

That's it for now,
Arik Poznanski.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

6 תגובות

  1. Offir29 באוגוסט 2011 ב 16:09

    So what is the best practice ?

    להגיב
  2. arik29 באוגוסט 2011 ב 16:46

    That's written in the summary (beginning of the post)

    "In a typical WPF application you should use Application.Current.DispatcherUnhandledException for exceptions generated on the UI thread and AppDomain.CurrentDomain.UnhandledException for all the other exceptions."

    להגיב
  3. yoav29 באוגוסט 2011 ב 21:59

    Thanks for the post.

    could you please elaborate on how to use this event?

    להגיב
  4. arik29 באוגוסט 2011 ב 22:41

    yoav, what do you mean?
    you should handle expected exceptions using try-cache block
    and provide a cache-all for logging / custom error message using these events by simple registration

    להגיב
  5. Miky13 בספטמבר 2011 ב 14:10

    Is it really possible to have more than one UI dispatcher thread ?

    להגיב
  6. arik16 בספטמבר 2011 ב 4:49

    Miky, the dispatcher object exists per thread. you can create UI objects from a different thread. This is highly not recommended but there are some rare cases this could be proved usful.

    see more information on the following link:
    http://eprystupa.wordpress.com/2008/07/28/running-wpf-application-with-multiple-ui-threads/

    להגיב