Using a thread-safe dictionary in .NET C# Part 1: introduction

In this post we saw how to use the thread-safe counterpart of the Queue object, i.e. the ConcurrentQueue of T. The standard Dictionary class also has a thread-safe counterpart and it’s called ConcurrentDictionary which resides int the System.Collections.Concurrent namespace.

The ConcurrentDictionary is definitely a dictionary type but it can mimic other collection types if you need a thread-safe collection that doesn’t have a built-in concurrent counterpart such as a List. ConcurrentDictionary is more difficult to use than a standard dictionary so its usage cannot really be summarised in a single short post. Therefore we’ll go through the basics in a mini-series instead.

It implements the IDictionary interface just like Dictionary but some methods are hidden:

Read more of this post

Using a thread-safe queue collection in .NET

We looked at the Queue collection type in .NET in this post. We saw how it could be used as a first-in-first-out collection. A new element is placed at the end of the queue and the first element to be removed from it is the one in front of the queue.

A Queue is an ideal container for tasks. Let’s create a class called WorkTask to represent tasks. I didn’t want to call this object a “Task” so that it is not confused with the Task object in the Task Parallel Library (TPL). If you don’t know what TPL means then take a look at the post referenced at the end of this article.

Read more of this post

Thread-safe bags in .NET

Bags are very similar to Stacks and Queues. We saw that both stacks and queues order their elements in a well defined way: last-in-first-out and first-in-first-out respectively. Bags on the other hand are unordered collections. There’s no guarantee on how, i.e. in which order the elements will be retrieved.

Unlike stacks and queues, bags have no one-to-one single-threaded implementation in .NET. They are however implemented as thread-safe ConcurrentBag objects in the System.Collections.Concurrent namespace.

Read more of this post

Thread safe queues in .NET

We saw how standard Queues work in .NET in this post. Queues are first-in-first-out collections where the first element added to the collection will the first to be removed. Queues are ideal to model consumer-producer scenarios where a producer adds items to a queue which are then processed by a consumer in the order they came in.

If you’d like to have a Queue that is shared among multiple threads in a multi-threaded application then the “normal” Queue of T object won’t be enough. You can never be sure of the current state of the queue in the very moment when a certain thread tries to dequeue an item from it. The queue may have been modified by another thread just a millisecond before and then the Dequeue method will fail. In general you should be very careful with how you share the resources among different threads.

Read more of this post

Thread-safe stacks in .NET

We saw how Stacks work in .NET in this post. Stacks are last-in-first-out collections where the last element added to the collection will the first to be removed.

If you’d like to have a Stack that is shared among multiple threads in a multi-threaded application then the “normal” Stack of T object won’t be enough. You can never be sure of the current state of the stack in the very moment when a certain thread tries to pop an item from it. The stack may have been modified by another thread just a millisecond before and then the Pop method will fail. In general you should be very careful with how you share the resources among different threads.

Read more of this post

Modifying a shared integer in a thread-safe manner in .NET

The Interlocked class in the System.Threading namespace provides a number of useful methods to modify the value of an integer that is shared among multiple threads.

Consider the following code. It updates the same shared integer in a loop on 5 different threads and prints the final status at the end. 3 threads add 1 to the integer 600 times and 2 threads subtracts 1 600 times. Therefore we’re expecting the shared integer to be 600 at the end:

Read more of this post

Reading the outcome of parallel loops in .NET C#

The Parallel.For() and Parallel.ForEach() methods both return a ParallelLoopResult object. This object has two properties which you can use to read if Break or Stop have been called:

  • IsCompleted: true if all loop iterations have been completed without calling either Break or Stop
  • LowestBreakIteration: the index of the lowest iteration in which the Break method was called

Example:

ParallelLoopResult parallelLoopResult =
        Parallel.For(0, 10, (int index, ParallelLoopState parallelLoopState) =>
	{
		if (index == 5)
		{
			parallelLoopState.Stop();
		}
	});

Console.WriteLine("IsCompleted: {0}", parallelLoopResult.IsCompleted);
Console.WriteLine("BreakValue: {0}", parallelLoopResult.LowestBreakIteration.HasValue?       parallelLoopResult.LowestBreakIteration.Value
				: -1);

The properties return the following values:

IsCompleted (IC): false
LowestBreakIteration.HasValue (LBI): false

Here come the possible value pairs and their meaning:

  • IC true, LBI false: all iterations were completed without breaking or stopping
  • IC false, LBI false: Stop was called
  • IF false, LBI true: Break was called

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

Deferred execution in parallel LINQ in .NET C#

If you are familiar with LINQ then you are probably aware of the notion of deferred execution: queries are not carried out until they are needed. This is not different in parallel LINQ either. Let’s see an example:

Set up a data source:

int[] integerArray = new int[100];
for (int i = 0; i < integerArray.Length; i++)
{
	integerArray[i] = i;
}

Define a parallel query:

IEnumerable<double> results =
	integerArray.AsParallel().Select(item =>
	{
		return Math.Sqrt(item);
	});

The query has not been carried out at this point. It is carried out when the following foreach loop starts:

double sum = 0;
foreach (double result in results)
{
	sum += result;
}
Console.WriteLine("Total {0}", sum);

You can force query execution with the same extension methods as in “normal” LINQ, such as ToList, ToArray etc.:

IEnumerable<double> results =
	integerArray.AsParallel().Select(item =>
	{
		return Math.Sqrt(item);
	}).ToList();

In this case the query is executed as soon as it has been defined.

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

Handling exceptions in parallel LINQ in .NET C#

We saw in this and this post how to handle exceptions that Tasks throw. It is not much different in parallel LINQ: the exception will be wrapped in an AggregateException.

The exception will be throw when the query is executed. So defining a parallel query will not throw an exception even if you explicitly throw one within the query. If you force the execution of the query with extension methods such as ToList, ToArray, ForAll etc., then the exception will be thrown immediately. Let’s see an example.

Define the data source:

int[] integerArray = new int[100];
for (int i = 0; i < integerArray.Length; i++)
{
	integerArray[i] = i;
}

Define the query:

IEnumerable<double> query =
	integerArray.AsParallel()
	.Select(item =>
	{
		if (item == 50)
		{
			throw new Exception();
		}
		return Math.Sqrt(item);
	});

Go through the results and handle the exception:

try
{
	foreach (double item in query)
	{
		Console.WriteLine("Result {0}", item);
	}
}
catch (AggregateException aggregateException)
{
	aggregateException.Handle(exception =>
	{
		Console.WriteLine("Handled exception of type: {0}",
			exception.GetType());
		return true;
	});
}

Run the code with Crtl+F5. You’ll see that the exception is thrown when the items are processed and then it’s handled. Items that were processed when the exception was thrown will complete so don’t assume that the parallel loop is interrupted at that moment.

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

Cancelling a Task with a composite cancellation token in .NET C#

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;

You can create a composite token that consists of several other tokens. The Task will then be cancelled if any of the underlying tokens has been cancelled. Here’s how you create a composite token:

CancellationTokenSource cancellationTokenSourceOne = new CancellationTokenSource();
CancellationTokenSource cancellationTokenSourceTwo = new CancellationTokenSource();
CancellationTokenSource cancellationTokenSourceThree = new CancellationTokenSource();
CancellationTokenSource compositeTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSourceOne.Token, cancellationTokenSourceTwo.Token, cancellationTokenSourceThree.Token);

Use this composite in the constructor of the Task:

Task task = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100000; i++)
	{
		if (token.IsCancellationRequested)
	        {
		       Console.WriteLine("Task cancellation requested");
		       throw new OperationCanceledException(token);
	        }
        	else
        	{
         		Console.WriteLine(i);
        	}	 
	}
}, compositeTokenSource.Token);

You can cancel the task by calling the Cancel() method of any of the tokens in the composite:


cancellationTokenSourceTwo.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 task = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100000; i++)
	{
		//shorthand
        	compositeTokenSource.ThrowIfCancellationRequested();
		Console.WriteLine(i);
	}
}, compositeTokenSource);

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

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: