25
votes

I am using the following event to catch unhandled exceptions in the main UI thread.

Application.ThreadException 

Unfortunately, it does not catch those unhandled errors in seperate threads. I am aware of

AppDomain.CurrentDomain.UnhandledException

However, this seems to shut down the application upon triggering, where as the former does not.

Is there a way to deal with unhandled exceptions on separate threads, without the application closing?

3
Yes, make sure your threads don't throw unhandled exception. As Eric Lippert puts it: "the safest thing to do is to assume that every unhandled exception is either a fatal exception or an unhandled boneheaded exception. In both cases, the right thing to do is to take down the process immediately." blogs.msdn.com/b/ericlippert/archive/2010/11/23/… - Ani
You forgot the best part of that article: "As Ripley said, when things go wrong you should take off and nuke the entire site from orbit; it's the only way to be sure" - Mike Caron
For those interested in finding the article, the previous link doesn't work anymore but you can go here: web.archive.org/web/20101124205815/http://blogs.msdn.com/b/… - John Thoits

3 Answers

25
votes

@Ani have already answered your question. Although I don't agree that unhandled exceptions in threads should terminate applications. Using threads usually means that you have some kind of server application. Bringing it down could result in a lot of angry users.

I've written a small piece about proper exception handling: https://coderr.io/exception-handling

You should always catch exceptions for threads. I usually use the following pattern:

  void ThreadMethod(object state)
  {
      try
      {
          ActualWorkerMethod();
      }
      catch (Exception err)
      {
          _logger.Error("Unhandled exception in thread.", err);
      }
  }

  void ActualWorkerMethod()
  {
      // do something clever
  }

It's a whole lot easier to find thread methods that doesn't handle exceptions properly by moving the logic into a seperate method and just keep the try/catch block in the thread method.

4
votes

Of course you should always handle all exceptions. But if you are currently incapable of doing so, you can try the following:

The application will crash/close after the UnhandledException event handler. You can just add a delay in the event handler to prevents this. Other threads with no exception (e.g. the main thread) can continue. So the application will not close and can continue. However, the thread with the exception will remain in sleep. And therefor you may get a "memory/thread leak".

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        // Log the exception, display it, etc
        Debug.WriteLine((e.ExceptionObject as Exception).Message);
        Thread.Sleep(100000000);
    }

At this moment there is not a better solution. You may find to change the config file, but i think that is just as dirty: https://stackoverflow.com/a/15348736

2
votes

Yes, you have to manually catch exceptions on threads.

However, this code:

void ThreadMethod(object state)
{
    try
    {
        ActualWorkerMethod();
    }
    catch (Exception err)
    {
        _logger.Error("Unhandled exception in thread.", err);
    }
}

void ActualWorkerMethod()
{
    // do something clever
}

can be simplified to this using PostSharp:

[LogExceptions]
void ActualWorkerMethod()
{
    // do something clever
}