Catching Unhandled Exception on Separate Threads

Catching unhandled exception on separate threads

@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.

Catch unhandled exceptions from any thread

You can use AppDomain.UnhandledExceptionHandler to handle uncaught exception.

Catch unhandled exceptions from a different thread

I tried madExcept, which is able to catch exception from different thread. After further digging, I found a way to catch exceptions silently with the help of madExcept.

procedure TForm1.HandleUncaughtException(const ExceptIntf: IMEException; var Handled: Boolean);
begin
SendExceptionToAnotherProcess(ExceptIntf.ExceptMessage);
Handled := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
madExcept.RegisterExceptionHandler(HandleUncaughtException, stTrySyncCallAlways, epMainPhase);
end;

Unhandled Exceptions thrown in threads are not caught

Your approach is correct. However, you will not be able to stop your application from terminating.

When an unhandled exception is thrown on a thread you have created in your application CurrentDomain_UnhandledException will be called allowing you to log or report the exception. However, unless the e.IsTerminating is false you will not be able to stop your application from terminating. You can read more about this behavior in Exceptions in Managed Threads.

If you find that CurrentDomain_UnhandledException is never called you should verify that Application_Startup is called to setup the handler.

If you still are having problems you should verify that Utilities.DisplayUnhandledException does not throw an exception. This will also lead to immediate termination of your application. In particular, if e.ExceptionObject is not of type Exception casting it to Exception will throw an exception. However, under normal circumstances, when the exception object is not a managed exception, it will be wrapped in a RuntimeWrappedException.

To avoid termination of your application you need to catch the exception at "the top of the stack" of your thread method. If that is not possible because you do not have access to the code then the unhandled exceptions are an indication of buggy software, and even though it is inconvenient the best thing to do when a software bug is discovered is to terminate the application to avoid corruption.

Catching unhandled exception of a thread

Well, one way would be to use BackgroundWorker instead of a thread in your situation. You don't need a try block there, as errors will be automatically caught and passed to the handler you assign when the worker ends.

EDIT:

You can also use an event of BackgroundWorker to report progress to your form, so you can update your progress bar properly ;-)

Catching exceptions caused in different threads

Generally speaking, it's easiest to catch the exceptions within the thread itself.

But if you want to catch the exception separately from the thread function itself (and if you can use Task instead of the old Thread approach), you can write code like this:

var task = Task.Factory.StartNew(() =>
{
throw new Exception("Test");
});

task.ContinueWith(t => handleException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);

This uses ContinueWith() to call another method after the first thread has finished and an exception occurred, so you can log the exception or whatever:

static void handleException(AggregateException exception)
{
foreach (var ex in exception.Flatten().InnerExceptions)
Console.WriteLine(ex.Message);
}

This doesn't really let you fix anything up - the only sensible way to do that is to handle the exceptions properly in the thread function itself.

Catching Unhandled Exceptions in Child Threads in WPF

Try hooking up to the AppDomain.CurrentDomain.UnhandledException event as well.



Related Topics



Leave a reply



Submit