Summary of thread-safe collections in .NET

The System.Collections.Concurrent namespace has 4 thread-safe collections that you can use in multi-threaded applications. The starting point is that you have a multi-threaded app where the same collection needs to be accessed by different threads. In that case the well-know collection types, like HashSet, List, Dictionary etc. simply won’t be enough.

If many different threads have access to the same resource then there’s no guarantee on the state of that resource in the moment a thread accesses it in some way: deletion, lookup, insertion or modification. Another thread may have accessed the same resource just milliseconds before that and the other thread will access the resource under the wrong assumptions. You’ll end up with buggy code with unpredictable results and ad-hoc fixes and patches that probably won’t solve the root of the problem.

Read more of this post

Advertisement

Introduction to generics in C# Part 6

Introduction

In the previous post we looked at constraints on generic type parameters using the ‘where’ keyword. We looked at an example where we wanted to limit the usage of an interface, IPropertiesPrinter, to those objects that implement another interface, namely IPrintable. We wanted to make sure that the generic type, i.e. the object to be printed, will have the GetProperties() method available. Without the constraint the generic object would only have the methods inherited from the Object class, such as ToString and GetHashCode.

In this post we’ll look at an example where not even constraints seem to provide a solution. I wanted to include this example in this series to show that sometimes not even generics can help create generic code.

Read more of this post

Introduction to generics in C# Part 5

Introduction

In the previous post we looked at how to declare multiple type parameters. We saw that it was a very simple thing to do. We just add as many parameters as we need and separate them by a comma. It’s perfectly fine to refer to those parameters later on in the class level functions. It’s equally fine to put multiple parameters on the function level as well if you don’t want to make the entire class generic.

In this post we’ll take a quick look at parameter type constraints.

Read more of this post

Introduction to generics in C# Part 4

Introduction

In the previous post we saw how to build generic functions. It’s not necessary to make an entire class generic if we want to keep the functions independent of any class level type parameters. We saw an example, a configuration settings reader, where it was unnecessary to declare the return type on the class level. That would put a constraint on the usage of a single configuration reader instance. Instead, we let the caller define the return type on the ReadConfigurationValue function which makes the configuration reader class more flexible.

In this post we’ll look at declaring multiple generic parameters.

Read more of this post

Introduction to generics in C# Part 3

Introduction

In the previous post on generics we looked at an example of reading application settings from a configuration file. Application settings come in key-value pairs where the value can be of different type: string, integer, boolean and various others. The generic ConfigurationReaderService helped us improve the non-generic code where the function caller had to take care of the type conversion and validation steps.

In this post we’ll further improve our code by looking into generic methods.

Read more of this post

Introduction to generics in C# Part 2

Introduction

In the previous post we started looking into generics in .NET. We also saw an initial example where an abstract base class had a type parameter to define the type of the Id property. The implementing classes could then all derive from this generic class and define their Id type along the way.

In this post we’ll look at another example where generics can be useful.

Read more of this post

Introduction to generics in C# Part 1

Introduction

Generics is a way to generalise your code in .NET. We can generalise the types that an object and/or a function operates on. With generics we can reuse the same portion of code with multiple types. If used in appropriate places it can be a great tool against code duplication.

Generics is nothing new, it was a new language feature in .NET 2.0.

Read more of this post

Thread safe collections in .NET: ConcurrentQueue

Concurrent collections in .NET work very much like their single-thread counterparts with the difference that they are thread safe. These collections can be used in scenarios where you need to share a collection between Tasks. They are typed and use a lightweight synchronisation mechanism to ensure that they are safe and fast to use in parallel programming.

Concurrent queues

If you don’t know what Queues are then you can read about them here. The Queue of T generic collection has a thread-safe counterpart called ConcurrentQueue. Important methods:

  • Enqueue(T element): adds an item of type T to the collection
  • TryPeek(out T): tries to retrieve the next element from the collection without removing it. The value is set to the out parameter if the method succeeds. Otherwise it returns false.
  • TryDequeue(out T): tries to get the first element. It removes the item from the collection and sets the out parameter to the retrieved element. Otherwise the method returns false

The ‘try’ bit in the method names implies that your code needs to prepare for the event where the element could not be retrieved. If multiple threads retrieve elements from the same queue you cannot be sure what’s in there when a specific thread tries to read from it.

Example

Declare and fill a concurrent queue:

ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>();

for (int i = 0; i < 5000; i++)
{
	concurrentQueue.Enqueue(i);
}

We’ll want to get the items from this collection and check if all of them have been retrieved using a counter. The counter will also be shared among the threads using the ‘lock’ technique we saw in this post – or actually something that is similar to the ‘lock’ keyword: the Interlocked class. Interlocked has an Increment method which accepts a ref int parameter. It will increment the incoming integer in an atomic operation.

int itemCount = 0;

Task[] queueTasks = new Task[20];
for (int i = 0; i < queueTasks.Length; i++)
{
	queueTasks[i] = Task.Factory.StartNew(() =>
	{
		while (concurrentQueue.Count > 0)
		{
			int currentElement;
			bool success = concurrentQueue.TryDequeue(out currentElement);
			if (success)
			{
				Interlocked.Increment(ref itemCount);
			}
		}
	});
}

The while loop will ensure that we’ll try to dequeue the items as long as there’s something left in the collection.

Wait for the tasks and print the number of items processed – the counter should have the same value as the number of items in the queue:

Task.WaitAll(queueTasks);
Console.WriteLine("Counter: {0}", itemCount);

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

Thread safe collections in .NET: ConcurrentBag

Concurrent collections in .NET work very much like their single-thread counterparts with the difference that they are thread safe. These collections can be used in scenarios where you need to share a collection between Tasks. They are typed and use a lightweight synchronisation mechanism to ensure that they are safe and fast to use in parallel programming.

Concurrent bags

Concurrent bags are similar to concurrent stacks and concurrent queues but there’s a key difference. Bags are unordered collections. This means that the order of the items is not the same as how they were inserted. So concurrent bags are ideal if you would like to share a List of T generic collection among several tasks.

Important methods:

  • Add(T element): adds an item of type T to the collection
  • TryPeek(out T): tries to retrieve the next element from the collection without removing it. The value is set to the out parameter if the method succeeds. Otherwise it returns false.
  • TryTake(out T): tries to get the first element. It removes the item from the collection and sets the out parameter to the retrieved element. Otherwise the method returns false

The ‘try’ bit in the method names imply that your code needs to prepare for the event where the element could not be retrieved. If multiple threads retrieve elements from the same list you cannot be sure what’s in there when a specific thread tries to read from it.

Example

The example is almost identical to what we saw for the collections discussed previously in the posts on TPL.

Declare and fill a concurrent bag:

ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();

for (int i = 0; i < 5000; i++)
{
	concurrentBag.Add(i);
}

Next we’ll try to take every item from the bag. The bag will be accessed by several tasks at the same time. The counter variable – which is also shared and synchronised- will be used to check if all items have been retrieved.

int counter = 0;

Task[] bagTasks = new Task[20];
for (int i = 0; i < bagTasks.Length; i++)
{
	bagTasks[i] = Task.Factory.StartNew(() =>
	{
		while (concurrentBag.Count > 0)
		{
			int bagElement;
			bool success = concurrentBag.TryTake(out bagElement);
			if (success)
			{
				Interlocked.Increment(ref counter);
			}
		}
	});
}

The while loop will ensure that we’ll try to take the items as long as there’s something left in the collection.

Wait for the tasks and print the number of items processed – the counter should have the same value as the number of items in the bag:

Task.WaitAll(bagTasks);
Console.WriteLine("Counter: {0}", counter);

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

Efficient linked lists in .NET

Sometimes you need a collection that’s modified a lot: you insert, update and remove items. A List of T is then inefficient as it needs to constantly rearrange all other items. The LinkedList class might be a better candidate.

A linked list is a doubly-linked list. Each item has a Next and Previous pointer to look at which element comes right before and after a particular object in the list. A linked list is very efficient at inserting and deleting items in particular.

Initialisation:

LinkedList<int> intList = new LinkedList<int>();

There are multiple ways to add a new item: AddAfter, AddBefore, AddFirst, AddLast.

Adding a new item on the top of the list:

intList.AddFirst(2);

Putting 3 ahead of 2:

intList.AddFirst(3);

It’s not possible to directly pull out an item with an indexer, such as [2].

You can, however, iterate through the collection:

foreach (var i in intList)
{
}

You can get a reference of the first item with the First property:

LinkedListNode<int> firstItem = intList.First;

You can then insert an item after that:

intList.AddAfter(first, 5);

This will add 5 in between 3 and 2.

Inserting before the first item is equally easy:

intList.AddBefore(first, 5);

You can get to the last item… can you guess how? Through the Last property.

The First and Last properties do not return an int, or the type that you provided in place of T. It returns a LinkedListNode of type T, which is int in this case. This object has a Previous and Next properties:

LinkedListNode<int> firstItem = intList.First;
firstItem.Previous;
firstItem.Next;

It also has a Value property which returns the actual value of the LinkedListNode object.

Another way of iterating through the list is the following:

LinkedListNode<int> item = intList.First;
while (item != null)
{
    int val = item.Value;
    item = item.Next;
}

Removing items can be done with methods such as RemoveLast(), RemoveFirst(), Remove(item).

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: