本随笔续接:.NET 同步与异步 之 警惕闭包(十)
无论之前说的锁、原子操作 还是 警惕闭包,都是为安全保驾护航,本篇随笔继续安全方面的主题:线程安全的集合。
先看一下命名空间:System.Collections.Concurrent,常用的类型有(均为泛型):BlockingCollection<T>、ConcurrentBag<T>、ConcurrentDictionary<TKey, TValue>、ConcurrentQueue<T>、ConcurrentStack<T> 。
其中:ConcurrentBag<T> 为无序的集合、ConcurrentDictionary<TKey, TValue> 为词典类型。
ConcurrentQueue<T>、ConcurrentStack<T> 分别为队列 和 栈,而 BlockingCollection<T> 可以看做是 队列 和 栈的进一步封装调用,并提供了阻塞(超时)功能。
本随笔着重说两个类型:BlockingCollection<T> 和 ConcurrentDictionary<TKey, TValue>。
一、BlockingCollection<T>
1、先看一下 MSDN 上的Demo
/// <summary> /// MSDN Demo /// BlockingCollection<T>.Add() /// BlockingCollection<T>.CompleteAdding() /// BlockingCollection<T>.TryTake() /// BlockingCollection<T>.IsCompleted /// </summary> public void Demo1() { // Construct and fill our BlockingCollection using (BlockingCollection<int> bc = new BlockingCollection<int>()) { int NUMITEMS = 10000; for (int i = 0; i < NUMITEMS; i++) { bc.Add(i); } bc.CompleteAdding(); int outerSum = 0; // Delegate for consuming the BlockingCollection and adding up all items Action action = () => { int localItem; int localSum = 0; while (bc.TryTake(out localItem)) { localSum += localItem; } Interlocked.Add(ref outerSum, localSum); }; // Launch three parallel actions to consume the BlockingCollection Parallel.Invoke(action, action, action); base.PrintInfo(string.Format("Sum[0..{0}) = {1}, should be {2}", NUMITEMS, outerSum, ((NUMITEMS * (NUMITEMS - 1)) / 2))); base.PrintInfo(string.Format("bc.IsCompleted = {0} (should be true)", bc.IsCompleted)); } }