There’s only one ThreadExceptionHandler

There can only ever be one Application.ThreadException handler. Yes, you read that correctly.

To give some context, the core of our error reporting code in SmartAssembly adds event handlers to AppDomain.CurrentDomain.UnhandledException (for general exceptions) and Application.ThreadException (for winforms exceptions) to display our error reporting dialog, or send the unhandled exception details back to the application developers as a bug report.

I was recently debugging an issue where any exceptions thrown after a call to Microsoft.Data.ConnectionUI.DataConnectionDialog.Show would not be picked up by our error reporting code. In other words, this:

would display our error reporting dialog, and this:

would display the standard .NET winforms error dialog. At some point during the call to Show, our exception handler was disappearing.

After quite a bit of digging, I noticed something odd about the definition of ThreadException:

Did you spot it? The add method uses = rather than += to assign the new event handler, replacing any existing handlers! And indeed, the DataConnectionDialog.Show was adding & removing it’s own exception handler during the method, deleting ours in the process. This bug is obviously a typo, as the remove method uses -=, as it should.

Microsoft has known about this since 2005, but (as of .NET 4) have yet to fix this typo. In the meantime, don’t trust that any ThreadException handlers you add will still be there if an exception gets thrown!