So far I have been enjoying the beta of Windows 7 and the new version of Windows Media Player 12. I would consider myself a heavy user of Windows Media Player. I use it to as my default music player, sync my music to my Windows mobile device, and to stream home movies to my Xbox 360. If something is not working quite right, I would probably encounter it.
There are a few bugs, with newest version of Media Player, that I hope will be fixed in the final version. I’ve had to rebuild my media library on several occasions and Media Player does not always recognize when I have added new music or videos. One of the features I miss, from version 11, is the ability to force it to look for new content. With version 12, the library seems to refresh with a background task and there is no way to force it. Note to Microsoft: Perhaps a better implementation would be a file watcher on the library directories.
If you want to rebuild you library,
- Shutdown windows media player.
- Stop the media sharing service. Go to Start->Control Panel->All Control Panel Items->Administrative Tools->Services. Right-click on the “Windows Media Player Network Sharing Service” and select Stop.
- Navigate to “c:\Users\”your username”\AppData\Local\Microsoft\Media Player. Now delete the files named CurrentDatabase_***.wmdb and LocalMLS_*.wmdb.
- Start the media sharing service.
- Now start Windows Media Player and watch it build up your library again.
Just like my previous post on dealing with unhandled exceptions in WinForms, I’ll be talking about how to accomplish the same thing in WPF. When your WPF application encounters an unhandled exception, the default .NET exception handler for WPF displays the following dialogs to the user.

There is not much information in these dialogs that would tell the user what went wrong. More importantly there is very little information for you as the developer in these dialogs that would help you find out what went wrong. Without stating everything I said in my previous post all over again, I’ll just say that there is a better option by replacing the default unhandled exception handler with your own.
My same disclaimer applies to this post as well. I grabbed most of the samples your about to see from MSDN (with some tweaks). However it was much harder to find them for WPF, and I had to combine two different sample apps to get you the complete solution for UI thread exception handling and non-UI thread exception handling.
Unlike the WinForm example, where we had to register for two events, there is only one DispatcherUnhandledException event that we have to be concerned about in WPF. You register your handler for this in the App.xaml.
1: <Application
2: x:Class="DispatcherUnhandledExceptionSample.App"
3: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5: StartupUri="MainWindow.xaml"
6: DispatcherUnhandledException="App_DispatcherUnhandledException" />
Next lets look at our code-behind for App.xaml and the handler function App_DispatcherUnhandledException().
1: void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
2: {
3: // Possible things to do:
4: // Write to the system event log
5: // Log to a text file
6: // Take a screen shot
7: // Display a friendly message to the user about what happened and what they should do next.
8:
9: // In this sample I am just dumping the error to a message box for you to see.
10: // THIS IS NOT A BEST PRACTICE.
11: var stringBuilder = new StringBuilder();
12: stringBuilder.AppendFormat("{0}\n", e.Exception.Message);
13: stringBuilder.AppendFormat(
14: "Exception handled on main UI thread {0}.", e.Dispatcher.Thread.ManagedThreadId);
15:
16: // attempt to save data
17: var result = MessageBox.Show(
18: "Application must exit:\n\n" + stringBuilder.ToString() + "\n\nSave before exit?",
19: "app",
20: MessageBoxButton.YesNo,
21: MessageBoxImage.Error);
22: if (result == MessageBoxResult.Yes)
23: {
24: // Save data
25: }
26:
27: // Return exit code
28: this.Shutdown(-1);
29:
30: // Prevent default unhandled exception processing
31: e.Handled = true;
32: }
There is not much required of this handler function other than the last line of code on line 31. We set the handled property to true so that the .NET framework does not display its own handler for the exception. If we were only concerned with exceptions that occurred on the UI thread, that would be all that is to it!
Next let’s look at how we can also handle exceptions
that occur in other worker threads by using a Dispatcher. I’ve created a simple form, similar to the
previous WinForm example, that has two buttons on it – one for generating an exception on the UI thread and another that generates an exception on a worker thread. Here are the important functions on that form:
1: private void StartSecondaryWorkerThreadButton_Click(object sender, RoutedEventArgs e)
2: {
3: // Creates and starts a secondary thread in a single threaded apartment (STA)
4: var thread = new Thread(this.MethodRunningOnSecondaryWorkerThread);
5: thread.SetApartmentState(ApartmentState.STA);
6: thread.IsBackground = true;
7: thread.Start();
8: }
9:
10: private void MethodRunningOnSecondaryWorkerThread()
11: {
12: try
13: {
14: WorkerMethod();
15: }
16: catch (Exception ex)
17: {
18: // Dispatch the exception back to the main UI thread. Then, reraise
19: // the exception on the main UI thread and handle it from the handler
20: // the Application object's DispatcherUnhandledException event.
21: int secondaryWorkerThreadId = Thread.CurrentThread.ManagedThreadId;
22: Application.Current.Dispatcher.Invoke(
23: DispatcherPriority.Send,
24: (DispatcherOperationCallback)(arg =>
25: {
26: // THIS CODE RUNS BACK ON THE MAIN UI THREAD
27: throw ex;
28: }),
29: null);
30:
31: // NOTE - Application execution will only continue from this point
32: // onwards if the exception was handled on the main UI thread.
33: // by Application.DispatcherUnhandledException
34: }
35: }
36:
37: private void WorkerMethod()
38: {
39: // This method would do real processing on the secondary worker thread.
40: // For the purposes of this sample, it throws an index out of range exception
41: string msg = string.Format(
42: "Index out of range exception raised on secondary worker thread {0}.",
43: Dispatcher.CurrentDispatcher.Thread.ManagedThreadId);
44: throw new IndexOutOfRangeException(msg);
45: }
Where all of the trickery happens is in the MethodRunningOnSecondaryWorkerThread() function. Here we have a try catch block with a generic exception handler (code smell – I know, but there is no way around it) that wraps the execution of the WorkerMethod(). After we catch the exception, we invoke a Dispatcher to execute some code on the main UI thread. All we do is re-throw the exception and our handler for the DispatcherUnhandledException event, in App.xaml, will catch the error. That’s it.
You can download the full sample code
here.
Okay here is the scenario for this blog. Your application crashes, and the user gets this cryptic error dialog that they have seen a hundred times with other applications, and they dismiss it without blinking an eye. They call you up or send you an email that said they had a problem with your app. The first thing you ask is “Did you click on the Details button”? The answer is almost always no. It gets worse. If your application had an unhandled exception in a worker thread, then the thread will exit silently, and the user may not even know there is a potential serious problem. You can try to look in the application log to see if you can figure out the problem, but you may not see the error that caused the crash because your application did not handle it. Alas, you have to resort to try and re-create the problem which may or may not pan out. Despite all of your good programming practices of using mocks, and unit tests to figure out every conceivable error scenario, your app somehow encountered an exception you didn’t expect.
Wouldn’t it be nice if the user was presented a nice friendly message telling them you are sorry your application encountered a problem and give them a chance to save any data? In the background you could also be logging the heck out of every detail of the exception and even taking a screen shot at the instant the crash happened. This blog will explain how you can be notified of an unhandled exception, and insert your own handler instead of the .NET framework version that shows that lovely dialog. This blog will describe how to do this in Winforms. My next blog post will describe how to deal with unhandled exceptions in WPF.
First a disclaimer. All of these code snippets are taken directly from MSDN (with slight modification). I hate bloggers that just regurgitate MSDN docs. In this case however, there are so many developers out there that do not know about this feature -- I feel compelled to blog about it to raise awareness.
There are two types of handlers you need to register in your WinForms application. The ThreadException event is for unhandled exceptions in your UI thread, and the UnhandledException event is for non-UI thread exceptions. The later event needs to be registered for every AppDomain that your application creates.
Lets take a look at some code:
1: [STAThread]
2: [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
3: private static void Main()
4: {
5: // Add the event handler for handling UI thread exceptions to the event.
6: Application.ThreadException += UIThreadException;
7:
8: // Set the unhandled exception mode to force all Windows Forms errors to go through
9: // our handler.
10: Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
11:
12: // Add the event handler for handling non-UI thread exceptions to the event.
13: AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
14:
15: Application.Run(new Form1());
16: }
This is the main function of your WinForms app. On line 2 we have an security attribute that gives our application permission to add our event handler to the AppDomain. To add a handler for unhandled exceptions on the UI thread, requires two lines of code. Line 6 adds our handler for unhandled exceptions on the UI thread and the second, on line 10, tells the framework how we want the exception to be routed. In this case, we want to catch the exception. Next, on line 13, we can add our handler for non-UI thread unhandled exceptions. Now that all of the handlers are registered, we can show the main form.
Now lets look at our handler for the UI thread:
1: private static void UIThreadException(object sender, ThreadExceptionEventArgs t)
2: {
3: DialogResult result = DialogResult.Cancel;
4:
5: try
6: {
7: result = MessageBox.Show("UIThreadException caught", "Error", MessageBoxButtons.AbortRetryIgnore);
8: }
9: catch
10: {
11: Application.Exit();
12: }
13:
14: // Exits the program when the user clicks Abort.
15: if (result == DialogResult.Abort)
16: {
17: Application.Exit();
18: }
19: }
When an unhandled exception occurs on the main UI thread, you do have the option, in your handler, to figure out if you want to ignore the error or retry the last operation that failed. I do not recommend this. In my opinion, you would have to know what kind of error occurred in order to know if it is safe to continue running the app. Since this is a handler for errors you are not expecting, it doesn’t seem likely you will know what to expect here. All of your expected exception handling should be done elsewhere in your code.
Next lets look at the handler for the non-UI thread:
1: private static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
2: {
3: try
4: {
5: Exception ex = e.ExceptionObject as Exception;
6: MessageBox.Show("CurrentDomainUnhandledException caught", "Error", MessageBoxButtons.OK);
7: }
8: finally
9: {
10: Application.Exit();
11: }
12: }
When this handler is called, you have no choice but to exit the application after the handler is finished. Just log what information you can, notify the user with a friendly message, and exit.
Some final notes on the handlers. Hopefully you have noticed that both of my handlers are wrapped in try blocks. It is very important that your handler function does not throw any exceptions. Also do not follow my example by showing a message box with all of nitty-gritty details of the exception. The user does not care, and they are not reliable to relay that information back to you. Give the user a friendly message that you are sorry that the application has encountered an error, and give them instructions on what to do next. Give them a link to submit a problem report, or tell them how to gather application logs. Also you may give them an option to save any data (although the data may be corrupt at least it is will not be gone).
You might be asking the question at this point. Why can’t I just put a try catch block around Application.Run()?
1: try
2: {
3: Application.Run(new Form1());
4: }
5: catch (Exception)
6: {
7: // handler code here.
8: }
This will work for most exceptions. However before .NET 2.0, there were non-CLS compliant exceptions that did not inherit from System.Exception. I don’t know if there are any exceptions out there today that do not inherit from System.Exception. Also I do not know what happens if I reference an assembly that was built on the older .NET 1.0 and that assembly throws a non-CLS compliant exception. Also it will not work for exceptions in non-UI threads. I just do not want to take the chance. This solution is bullet proof and will work for every type of exception that is encountered.
You can download the full sample code here.