C# and concurrency: a look at the concurrent classes
Posted: (EET/GMT+2)
The .NET platform includes a set of thread-safe collection classes under the System.Collections.Concurrent namespace. The classes there are designed for scenarios where multiple threads add and remove items without you having to lock collections manually.
Some of the main types are:
ConcurrentDictionary<TKey, TValue>: a thread-safe key/value store.ConcurrentQueue<T>: a FIFO queue for producer/consumer scenarios.ConcurrentStack<T>: a LIFO stack.ConcurrentBag<T>: an unordered bag for work items.BlockingCollection<T>: a wrapper that adds blocking and bounding on top of an underlying collection (often aConcurrentQueue<T>).
Here's a simple example about using the ConcurrentDictionary:
using System.Collections.Concurrent;
using System.Threading.Tasks;
var dict = new ConcurrentDictionary<int, string>();
Parallel.For(0, 1000, i =>
{
dict.TryAdd(i, "Value " + i);
});
string value;
if (dict.TryGetValue(42, out value))
{
Console.WriteLine(value);
}
Here's another example of a producer/consumer with BlockingCollection:
var queue = new BlockingCollection<string>();
Task.Run(() =>
{
foreach (var item in queue.GetConsumingEnumerable())
{
Console.WriteLine("Processing " + item);
}
});
queue.Add("Task1");
queue.Add("Task2");
queue.CompleteAdding();
These classes simplify concurrent code significantly compared to manual locking. They are available in .NET Framework 4 and later, and in .NET Core.