Introduction
Exception handling is very vital for any software. We use our traditional way of handling exceptions of our code using Try/ Catch / Finally
block to handle runtime exceptions. We write our code inside a try
block and wait for the error being generated from the code, and write our proper catch
block to handle the Exception
if generated while running the code. Compiler handles all these problems and calls the appropriate catch
automatically. We write various Catch
blocks which handle the exception based on the type of exception that occurs. After the exception is handled properly, the normal execution of the program remains unaffected.
Well, this is very normal for any program. Even though we always try to make our code Ultra-Defensive, sometimes we fall in a prank when our client tells us about an Weird Exception that took place in their environment. Maybe, you browse the whole solution to find the problem, and don't find the actual issue. Yes, there are lots of exceptions that you cannot handle from your code.
Exception on UI Thread (Dispatcher)
Say your client could not install your application properly and missed out a couple of DLLs or missed out themes that you might have used from your code. In these scenarios, we need to use a global handler which you want to be executed whenever any exception is not handled by your code, or exception which is generated in extreme cases. In case of WPF applications, Application.DispatcherUnhandledException
comes in most handy in this situation.
WPF application object comes with DispatcherUnhandledException
, an event which is generated automatically whenever application is going to be crashed after an exception is generated. Let us generate and see the code on how you could handle these situations:
<Application x:Class="UnhandledExceptionHandler.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml"
Startup="Application_Startup"
DispatcherUnhandledException="Application_DispatcherUnhandledException">
<Application.Resources>
</Application.Resources>
</Application>
In the above code, you can see that I have added an EventHandler
for the application. The DispatcherUnhandledException
is called whenever the UI thread of the application generated an unhandled exception. To handle the exception, we write:
public bool DoHandle { get; set; }
private void Application_DispatcherUnhandledException(object sender,
System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
if (this.DoHandle)
{
MessageBox.Show(e.Exception.Message, "Exception Caught",
MessageBoxButton.OK, MessageBoxImage.Error);
e.Handled = true;
}
else
{
MessageBox.Show("Application is going to close! ", "Uncaught Exception");
e.Handled = false;
}
}
Importance of e.Handled
In the above code, I have placed a bool
property to determine if we need to handle the exception or not. You can see, if the value of DoHandle
is true
, I have set e.Handled = true
and vice-versa.
DispatcherUnhandledExceptionEventArgs
comes with few arguments.
- Exception: This object is the actual Exception that is generated from the application.
- Dispatcher: You might already know, Dispatcher points to the UI thread.
- Handled: It determines if the block has already
handled
the exception. The default value for e.Handled = false
, which means, the application still has the exception.
Thus in our case, if you do not put e.Handled = true
, the application will eventually crash down. So it is very important to set the property e.Handled = true
after you handle the exception.
Please note: Sometimes, even though you did set e.Handled = true
, the application might crash. This depends on the severity of the Exception.
Exception on Custom Threads
In case of your custom Threads, your exception will not be caught by the DispatcherUnhandledException
. This event hooks only the UI thread, and is only called when the UI thread gets an exception which crashes the program. If you need to handle the Exception occurring from a Non UI Thread, you can handle the UnhandledException
that comes with AppDomain
.
If you are not running your Threads
in a new AppDomain
, you might handle the UnhandledException
event of AppDomain
, and this would be called whenever any thread that runs on the AppDomain
gets an Exception
Object. To make it most simple, I have used AppDomain.CurrrentDomain.UnhandledException
.
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
MessageBox.Show(ex.Message, "Uncaught Thread Exception",
MessageBoxButton.OK, MessageBoxImage.Error);
}
In the above code, you can see that I have handled the CurrentDomain.UnhandledException
. This event will get executed whenever any UnhandledException
occurs inside a NonUI Thread
.
Sample Application

To demonstrate, I have provided a sample application. The application has a Button
, which generates Exception, three RadioButton
to demonstrate the exception on various scenario and one CheckBox
to invoke the Exception from inside a Non-UI thread.
If you run the application, you will see that the first RadioButton
gives you a MessageBox
that it is handled within the block which generates the Exception. The second RadioButton
will catch the Exception on DispatcherUnhandledException
handler, and the third will crash the whole application.
You can download the source here.
I hope you like this post. Thank you all for reading.