Exception handling in the .NET Task Parallel Library with C#: a safety catch-all

In the previous posts on exception handling in Tasks (here, here, and here) we saw how to handle exceptions thrown by tasks. We saw that unhandled aggregate exceptions will be re-thrown by the default escalation policy. This will lead your application to be terminated immediately. If there are other ongoing tasks in that moment then those will be terminated too.

There can be situations that your application uses threads to such an extent that you either cannot put a try-catch block around every single Task.Wait, Task.WaitAll etc. calls or you simply forget it. There is a way to subscribe to all unhandled aggregate exceptions that the task scheduler encounters. You can then decide what to do with the exception there.

The task scheduler has an UnobservedTaskException event. It’s straightforward to subscribe to that even with the += operator.

TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

…where the event handler looks like this:

static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
	e.SetObserved();
	((AggregateException)e.Exception).Handle(ex =>
	{
		Console.WriteLine("Exception type: {0}", ex.GetType());
		return true;
	});
}

The SetObserved() method tells the task scheduler that the exception has been taken care of so there’s no need for it to bubble up. The UnobservedTaskExceptionEventArgs object has an Exception property that must be cast to an AggregateException. From then on you can call the Handle() method of the aggregate exception as we saw before.

Start a couple of new tasks:

Task.Factory.StartNew(() =>
{
	throw new ArgumentException();
});

Task.Factory.StartNew(() =>
{
	throw new NullReferenceException();
});

Wait a bit for the tasks to finish:

Thread.Sleep(100);

Run the code with Ctrl+F5 and… er… nothing happens really. The event handler is never triggered. You won’t see the aggregate exception type printed on the console window. What happened? The UnobservedTaskException handler will be called when the tasks with the unhandled exception have been collected by the garbage collector. As long as we are holding a reference to the two tasks the GC will not collect them, and we’ll never see the exception handler in action.

If we want to force the event handler to be fired then you can add the following two lines just below the Thread.Sleep bit:

GC.Collect();
GC.WaitForPendingFinalizers();

Run the code again and you’ll see the exception messages in the console window.

Note the following: in .NET4.5 there’s a new configuration element that specifies whether unhandled task exceptions should terminate the application or not:

<ThrowUnobservedTaskExceptions
   enabled="true|false"/>

True: terminate the process if an unhandled exception is encountered.
False (default): the exact opposite of the True case

In .NET4 the default behaviour is to terminate the process as we saw. In .NET4.5 it’s the exact opposite: unhandled exceptions still cause the UnobservedTaskException event to be raised, but the process will not be terminated by default. The exception will be silently ignored. So if you want to simulate .NET4 behaviour in a multi-threaded .NET4.5 application you’ll need to set the above mentioned configuration setting to true in the config file.

View the list of posts on the Task Parallel Library here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Exception handling in the .NET Task Parallel Library with C#: a safety catch-all

  1. Atilla Selem says:

    Hallo Andras. Es lässt sich dem Link nicht erreichen. “Exception handling in the .NET Task Parallel Library with C#: reading task properties”.
    Not Found, Error 404.
    Danke für alle Efforts 🙂
    Lg,
    Atilla

Leave a Reply to Atilla Selem Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: