Summary - Concurrent collections
Combine ConcurrentDictionary and BlockingCollection to write a work queue.
Summary - Concurrent collections
In this summary you will combine ConcurrentDictionary and BlockingCollection to write a small work queue. The producer adds tasks to a blocking queue, the consumer drains them and counts in a ConcurrentDictionary.
The methods from the last five lessons (GetOrAdd, Add, CompleteAdding, GetConsumingEnumerable and OrderBy) work together here. Keeping it single-threaded keeps the output deterministic.
Work queue design
The producer adds three tasks to a BlockingCollection<string> called work and calls CompleteAdding. The consumer drains each task with GetConsumingEnumerable and stores its name and length in a dictionary with results.GetOrAdd(item, item.Length).
You print results sorted with OrderBy(k => k.Key). This shows producer-consumer and dictionary patterns together.
Exercise Assemble the work queue
work is a BlockingCollection<string>, results a ConcurrentDictionary<string, int>. Add "apple", "banana", "cherry" to work and call CompleteAdding. Drain items with GetConsumingEnumerable and store each with results.GetOrAdd(item, item.Length). Then print $"{kvp.Key}: {kvp.Value}" sorted by OrderBy(k => k.Key).
Show example solution
Add three items with work.Add, call CompleteAdding. With GetConsumingEnumerable, do results.GetOrAdd(item, item.Length). Print with OrderBy(k => k.Key).
Example solution:
using System;
using System.Collections.Concurrent;
using System.Linq;
class Program
{
static void Main()
{
var work = new BlockingCollection<string>();
var results = new ConcurrentDictionary<string, int>();
work.Add("apple");
work.Add("banana");
work.Add("cherry");
work.CompleteAdding();
foreach (var item in work.GetConsumingEnumerable())
{
results.GetOrAdd(item, item.Length);
}
foreach (var kvp in results.OrderBy(k => k.Key))
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
}
}
Test yourself
-
Match each collection to its role
- ConcurrentDictionary
- Thread-safe dictionary
- ConcurrentQueue
- Thread-safe FIFO
- BlockingCollection
- Producer-consumer blocking
-
Which collection best fits a producer-consumer work queue?
- ConcurrentDictionary
- ConcurrentBag
- ConcurrentStack
- BlockingCollection
Show answer
BlockingCollection — Correct. BlockingCollection is designed for producer-consumer.
-
Complete the BlockingCollection declaration
var queue = new ____();Show answer
var queue = new BlockingCollection<string>();