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

Advertisements

A common platform for concurrent bags, stacks and queues in .NET

We’ve looked at the available concurrent collections in .NET before:

3 of these objects implement the same interface. Can you guess which three are similar in some sense? Stacks, bags and queues differ from dictionaries in that elements in those collections cannot be retrieved by an index of any sort. You can take/pop/dequeue the elements one by one but you cannot get to element #3 without first removing all elements before that.

Read more of this post

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.

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

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.

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT BEST PRACTICES WITH MICROSOFT STACK & ANGULAR

Cyber Matters

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

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: