Reputation: 6226
I'm looking for some guidance on best practices on handling exceptions in events. Currently, when exceptions are thrown in my application, the exception message is displayed in a pop up dialog and then the application restarts after hitting ok. The issue I'm seeing is that a lot of exceptions are occurring in the event handlers of some third party libraries and these exceptions are swallowed and never displayed since they are on a background thread. Here are a few solutions that various people have thought of and I would like to know of any of these are the best approach.
Upvotes: 0
Views: 1693
Reputation: 27515
If you're hooking the AppDomain.UnhandledException event, then the issue isn't the fact that they might be calling back on a background thread, but rather than the third-party library is explicitly swallowing exceptions thrown by the handlers. This is a badly behaving library, but, since you're writing the event handler code, you can catch the exceptions in the event handler and force the application to shut down.
Since the third-party library can't be stopped by throwing an exception, you can force the thread to terminate by calling:
Thread.CurrentThread.Abort();
Thread.Abort()
is generally considered a bad practice, but it's slightly less dangerous here, as you are aborting yourself and therefore won't be injecting the exception into potentially nasty locations (you also know that the thread is not in an unmanaged context, so it will abort right away.) It's still a nasty hack, but the third-party application isn't giving you much choice. ThreadAbortException cannot be 'stopped', so the third-party code will terminate its thread as soon as it reaches the end of its exception handlers (even if they try to swallow it). If the third-party library is really nasty, it might invoke lots of code in its catch or finally blocks, even using dirty tricks to stay alive like launching other threads, but it would have to be pretty malicious to do this.
To get the friendly error message behavior, you can marshal the Exception to your UI thread using a SynchronizationContext or Dispatcher to call your exception-handler display (the easiest way may be to just re-throw the exception; I recommend embedding it as an InnerException so that you don't lose stack trace.)
If you really distrust the library (and don't want to give it the opportunity to stay alive even through its catch and finally blocks), you can explicitly marshal to the UI thread with a blocking invoke (to display your error message in a friendly way) and then call Environment.FailFast()
to kill your process. This is a particularly harsh way to terminate (it will not call any cleanup code and literally tears down the process as quickly as possible), but it minimizes the possibility for any potentially damaging side effects if application state has become very corrupted. One possible thing to watch for here is that the UI thread could be blocked by some other UI invocation tied to the third-party code. If this happens, the application will deadlock. Again, this would be a pretty malicious thing for it to do, so you can probably ignore it.
Upvotes: 0
Reputation: 20571
None of the above. Instead hook up the events on the Application
and AppDomain
for unhandled exceptions.
Further Information: The global exception handling event for WPF applications Application.DispatcherUnhandledException
fires only for exceptions thrown on the main UI thread. However the AppDomain.CurrentDomain.UnhandledException
should fire on any unhandled exception in any thread (unfortunately there is no preventing the application from shutting down after ward it reaches here).
Did some quick research on best practices and found that it is recommend that you manually handle exceptions on the background threads with try\catch
block. Read the exception part on this page http://www.albahari.com/threading/ and also take a look at this StackOverflow question Catching unhandled exception on separate threads
Upvotes: 1
Reputation: 16162
Lets discuss your options the way you listed them:
1) Forward the background thread to the UI thread in every event handler in the application.
You should not and you can't! because:
2) Wrap the events in another class which has a try/catch around every method that invokes the event. The catch will then forward the exception to the UI thread if one occurs.
3) Get access to the third party libraries and put try/catch around where the events are being invoked, which could then be forwarded to the main application by a global event.
This is a bad choice, really, You should not change that code of third party libraries even if you can. because:
So what you have to do? The answer is some sort of what you are currently doing:
Whenever any exception thrown, log the exception restart your process, and at some point in your process send the logged bugs to your email and then start fixing them.
Upvotes: 1