First some background: I have a multi-threaded WinForms application that is doing interop to native dlls. This application crashes sometimes with unhandled exception and we
Yes, Application.ThreadException can only trap exceptions that are raised in the UI thread. In code that's run due to Windows notifications. Or in technical terms, the events that are triggered by the message loop. Most any Winforms event fit this category.
What it does not trap are exceptions raised on any non-UI thread, like a worker thread started with Thread.Start(), ThreadPool.QueueUserWorkItem or a delegate's BeginInvoke() method. Any unhandled exception in those will terminate the app, AppDomain.UnhandledException is the last gasp.
Going further down-hill, hardware exceptions that are raised in an unmanaged thread by native code that never made any managed CLR call can not be detected with any CLR mechanism. An AccessViolation (exception code 0xc0000005) is the most common cause of death. The only way to trap those is through the Windows API, SetUnhandledExceptionFilter(). This is hard to get right.
You can disable Application.ThreadException with Application.SetUnhandledExceptionMode(). Which is a wise thing to do, giving the user the Continue option doesn't make a lot of sense. Now all exceptions in managed threads behave the same, use AppDomain.UnhandledException to log them.
I highly recommend that you use the OS minidump generation instead of your own. This is for several reasons:
ThreadException
or UnhandledException
is started, the exception stack has already been unwound. Generating a minidump at that point will just point you to the handler, not the source of the exception.If your app is in the field, use WER. If you're doing in-house testing, use ProcDump. You can also just copy the minidump file while the Error Reporting dialog is active.
P.S. There are some exceptional conditions - most notably when doing p/Invoke - where neither ThreadException
nor UnhandledException
will work.
P.P.S. If you have a debuggable scenario, then try turning on the Managed Debugging Assistants relating to p/Invoke.
Application.ThreadException
will only be raised for unhandled exceptions on WinForms UI threads (see here.) Adding a handler for AppDomain.UnhandledException
could help in this case (though with some caveats, as described in the remarks section here.)