Unhandled exceptions in .NET 2.0 background threads
First a bit of history, in .NET 1.1 any exceptions that were not handled in a background thread that generated them were just lost, you had to remember to handle them within the failing thread or never see them again.
This 'feature' has been addressed in .NET 2.0 and now any unhandled exception in a background thread will cause the standard JIT/Debugger dialog to appear just as any unhandled exception in the primary UI thread would.
So code that was quietly failing in .NET 1.1. now starts to generate hard to ignore dialogs in 2.0:
If you do handle the exception in the background thread (as would normally be good practice) obviously no exception is raised in the primary thread and all is good. However, what happens if you want exception to be handled by the primary UI thread? say if you want to popup a dialog or change a statusbar so the user knows what is going on; you cannot easily do this from the background thread as .NET 2.0 has far tighter thread safety than previous versions.
To address the general problem of unhandled exception, in the primary thread you can set Application and AppDomain handlers, this is normally done in the Main() method as below:
1static class Program
2{
3\[STAThread\]
4static void Main()
5{
6 // Set the unhandled exception mode to force all errors to go through our handler.
7 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
8 // which we define here
9 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application\_ThreadException);
10
11 // Add the event handler for handling non-UI thread exceptions to the event.
12 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain\_UnhandledException);
13
14 Application.EnableVisualStyles();
15 Application.SetCompatibleTextRenderingDefault(false);
16 Application.Run(new Form1());
17}
18
19static void Application\_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
20{
21 HandleUnhandledException(e.Exception);
22}
23
24static void CurrentDomain\_UnhandledException(object sender, UnhandledExceptionEventArgs e)
25{
26
27 HandleUnhandledException(e.ExceptionObject as Exception);
28}
29
30static void HandleUnhandledException(Exception ex)
31{
32 MessageBox.Show(ex.Message, "Exception Caught from Program.cs", MessageBoxButtons.OK, MessageBoxIcon.Error);
33
34}
35}
With this code in place any exception throw by a a UI or non-UI method in the primary thread will be caught and handled. It will also catch any unhandled exceptions from a background thread. However, as they are still unhandled in the background thread itself (even though you handled them in primary thread) you still get the JIT/Debugger dialog (as well as your own MessageBox), so you have not gained much as far as user experience goes.
If you really need to handle exceptions between thread the answer is to use a call back in the background thread to handled the exception locally, then throw it again into the primary thread so it can picked up by the AppDomain handler. The code to do this is as follows:
1delegate void ExceptionCallback(Exception ex);
2
3void PassbackExceptionToMainThread(Exception ex)
4{
5 throw ex;
6}
7
8void Background(Object parameter)
9{
10 try { throw new ApplicationException("An exceptions from the thread"); }
11 catch (Exception ex){ this.BeginInvoke(new ExceptionCallback(PassbackExceptionToMainThread), ex); }
12}
13
14private void button1\_Click(object sender, EventArgs e)
15{
16 ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Background));
17}