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

Introduction

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.

Read more of this post

Advertisement

Monitoring Task cancellation in C# in a loop

You cannot directly interrupt a Task in .NET while it’s running. You can do it indirectly through the CancellationTokenSource object. This object has a CancellationToken property which must be passed into the constructor of the Task:

CancellationTokenSource cancellationTokenSource	= new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;

The cancellation token can be used as follows:

Task newTask = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100000; i++)
	{
		if (cancellationToken.IsCancellationRequested)
		{
			Console.WriteLine("Task cancel detected");
			throw new OperationCanceledException(cancellationToken);
		}
		else
		{
			Console.WriteLine(i);
		}
	}
}, cancellationToken);

We simply count up to 100000 in the Task body. Note the IsCancellationRequested property of the token. We monitor within the loop whether the task has been cancelled.

You can cancel the task by calling the Cancel() method of the cancellation token like this:

cancellationTokenSource.Cancel();

Note that this method only signals the wish to cancel a task. .NET will not actively interrupt the task, you’ll have to monitor the status through the IsCancellationRequested property. It is your responsibility to stop the task. In this example we throw an OperationCanceledException which is a must in order to correctly acknowledge the cancellation. If you forget this step then the task status will not be set correctly. Once the task has been requested the stop it cannot be restarted.

If that’s all you want to do, i.e. throw an OperationCanceledException, then there’s a shorter version:

cancellationToken.ThrowIfCancellationRequested();

This will perform the cancellation check and throw the exception in one step. The loop can thus be simplified as follows:

Task newTask = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100000; i++)
	{
		cancellationToken.ThrowIfCancellationRequested();
		Console.WriteLine(i);					
	}
}, cancellationToken);

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

Exception handling in the .NET Task Parallel Library with C#: reading task properties

We saw in this and this post how to catch and handle exceptions thrown by threads. A task has properties that let you read its state and determine what happened to it.

Read more of this post

Continuation tasks in .NET TPL: a simple continuation example

Tasks in .NET TPL make it easy to assign tasks that should run upon the completion of another task.

We’ll need a basic object with a single property:

public class Series
{
	public int CurrentValue
	{
		get;
		set;
	}
}

Declare a task that increases the CurrentValue in a loop and return the Series. This task is called the antecedent task.

Task<Series> motherTask = Task.Factory.StartNew<Series>(() =>
{
	Series series = new Series();
	for (int i = 0; i < 10000; i++)
	{
		series.CurrentValue++;
	}
	return series;
});

Declare the continuation task where we also use the antecedent as method parameter:

motherTask.ContinueWith((Task<Series> previousTask) =>
{
	Console.WriteLine("Final Balance: {0}", previousTask.Result.CurrentValue);
});

The antecedent task will then schedule the continuation task for you. If there are other tasks then they may run before or after the continuation tasks depending on the task scheduler.

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

Using immutable collections for thread-safe read-only operations in .NET

Sometimes you have a scenario where multiple threads need to read from the same shared collection. We’ve looked at the 4 concurrent, i.e. thread-safe collection types on this blog that are available in the System.Collections.Concurrent namespace. They can be safely used for both concurrent writes and reads.

However, if your threads strictly only need to read from a collection then there’s another option. There are collections in the System.Collections.Immutable namespace that are immutable, i.e. read-only and have been optimisied for concurrent read operations.

Read more of this post

Using the BlockingCollection for thread-safe producer-consumer scenarios in .NET Part 5

In the previous post we finished the basics of building producer-consumer scenarios with BlockingCollection in .NET. In particular we saw how to send a signal to the consumer that the producers have completed their tasks and no more items will be inserted into the work queue.

In this final post I just want to draw your attention to a couple of other fine-tuning methods in the BlockingCollection object.

Read more of this post

Using the BlockingCollection for thread-safe producer-consumer scenarios in .NET Part 4

In the previous post we saw how to wire up the producer and the consumer in a very simplistic producer-consumer scenario in .NET using a BlockingCollection. We started a number of producer and consumer threads and checked their output in the Debug window.

In this post we’ll see how we can send a signal to the consumer that all producers finished adding new items to the work queue. This is to simulate a scenario where you can determine in advance when all expected items have been added to the work queue.

Read more of this post

Using the BlockingCollection for thread-safe producer-consumer scenarios in .NET Part 3

In the previous post of this mini-series we started building our model for the producer-consumer scenario. We have two objects to begin with. First, WorkTask.cs which represents the task that’s added to the work queue by the producers and retrieved by the consumers to act upon. Second we have an object, WorkQueue to encapsulate the work queue itself. It will be the consumer of the work queue through the MonitorWorkQueue method.

We haven’t yet seen the the consumer class yet. We’ll do that in this post.

Read more of this post

Using the BlockingCollection for thread-safe producer-consumer scenarios in .NET Part 2

In the previous post we briefly went through the producer-consumer scenario in general. We also mentioned another class in the System.Collections.Concurrent namespace that we haven’t seen before, i.e. the BlockingCollection of T.

We’ll start looking into this object in this post.

Read more of this post

Using the BlockingCollection for thread-safe producer-consumer scenarios in .NET Part 1

We’ve looked at the 4 concurrent, i.e. thread-safe collections available in .NET:

We also mentioned that 3 of these, i.e. the concurrent queue, bag and stack implement the generic IProducerConsumer interface. They can be used in producer-consumer scenarios where one or more threads write to a work queue. They are the producers in the setup. One or more other threads then read from the same work queue in order to perform some task on them. These are the consumers. When the consumer takes an item from the work queue then that item is also removed from it so that it’s not processed more than once. If you need to build a scenario like that then you’ll obviously need thread-safe collections that can synchronise access to them in a reliable manner.

We haven’t seen before how a producer-consumer scenario can be built from scratch using the available classes in the System.Collections.Concurrent namespace. We’ll do that in this and the next couple of posts.

Read more of this post

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: