Global Exceptions HandlingAre you sure know the difference between the following events?

  • Dispatcher.UnhandledException
  • Application.DispatcherUnhandledException
  • AppDomain.UnhandledException
  • TaskScheduler.UnobservedTaskException

My dean in the university has been always saying that the first rule of programming is “Programs should not contain any errors” and the second rule of programming is “There are no programs written without errors”. So, sometimes, I’m sorry, but shit happens and uncaught exceptions occur and they fly freely until they reach the top of the execution stack, thus crushing your program. Global exceptions handling exists in order to react somehow to such horrible cases.
There is a bunch of events which fire up when an unhandled exception occurs. Let’s consider what events can help us. The most useful events as we already mentioned:

  • Dispatcher.UnhandledException
  • Application.DispatcherUnhandledException
  • AppDomain.UnhandledException
  • TaskScheduler.UnobservedTaskException

Exception on a Dispatcher Thread

The difference between the first two events is a little bit slick. The second one catches exceptions from the main UI dispatcher thread, while the first one catches exceptions from a specific UI dispatcher thread. Usually, they are the same, because in 99% of cases WPF application has only one UI-thread and because of that both that events catch exceptions from the same thread, from the main UI thread. The thing is that WPF is not restricted to have only one UI thread. You can create another UI thread with a corresponding Dispatcher. And in that case you will have to attach your handler to the UnhandledException event of the first dispatcher and the second dispatcher. Chances that you will never face such a situation in your entire life are very high. So, generally speaking you are free to attach handlers to any of these events.

Exception on a Worker Thread

An exception might be thrown from any worker thread in your application. In general, you can spawn the worker thread either by using Thread class directly or the modern API of Tasks. And regarding global exceptions handling, these cases are different. If an exception was thrown from a task, it can be caught only in the TaskScheduler.UnobservedTaskException (you also will see it in AppDomain.UnhandledException, but you can’t mark it as handled there) . On the contrary, if an exception was thrown from any other thread, except the UI-thread and threads spawned by Tasks, it can be caught only in the AppDomain.UnhandledException event.

You can’t actually handle the exception in the AppDomain.UnhandledException event. You can just log it. If you want your application to stay alive you need to add a directive in the configuration file of your application:

[code lang=”XML”]
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1" />
</runtime>
</configuration>
[/code]

Since the release of .NET 4.5 UnobservedTaskException does not kill the application. If you want to get back the old behavior you should add the following directive in the configuration file:

[code lang=”XML”]
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
</configuration>
[/code]
By the way, exceptions occurred within Tasks will not be thrown until corresponding tasks are not collected by the GC.

Fine, we’ve discussed Global Exceptions Handling in WPF. It can be a little bit confusing, just carefully think of all possible situations.
Thank you for visiting my blog. Subscribe to my blog, don’t miss the next exciting post!