傳統集合(List<T> 等)非執行緒安全。多執行緒同時讀寫會拋出 InvalidOperationException(「集合已修改,列舉操作無法執行」)。舊版解法需手動 lock,碼雜且易錯。.NET 4.0 引入無鎖/細粒度鎖的並行集合,簡化多執行緒開發。
| 類別 | 位於 | 對應傳統型別 | 特色 |
|---|---|---|---|
| ConcurrentQueue<T> | mscorlib.dll | Queue<T> | FIFO 佇列 |
| ConcurrentStack<T> | mscorlib.dll | Stack<T> | LIFO 堆疊 |
| ConcurrentDictionary<TKey,TValue> | mscorlib.dll | Dictionary<TKey,TValue> | 支援 AddOrUpdate/GetOrAdd Lambda 工廠 |
| ConcurrentBag<T> | System.dll | (新增) | 無序包袋,生產者/消費者模式 |
| BlockingCollection<T> | System.dll | (新增) | 界限封鎖集合,支援 CompleteAdding/逾時操作 |
var td = new ConcurrentDictionary<int, string>();
Func<int, string> gen = i => i.ToString();
Task.Factory.StartNew(() => {
for (int i=0; i<1000; i++) td.GetOrAdd(i, gen);
});
Task.Factory.StartNew(() => {
td.AddOrUpdate(0, gen, (k, old) => old + k);
Console.WriteLine(td[0]);
}).Wait();
GetOrAdd:鍵不存在時自動呼叫工廠產生值。AddOrUpdate:鍵存在時執行更新邏輯,否則新增。IProducerConsumerCollection<T>,提供下列關鍵方法:TryAdd(T) / TryTake(out T):原子性加入/取出。TryPeek(out T):檢視最後元素不移除。IEnumerable<T>)。var bag = new ConcurrentBag<string>();
Task.Factory.StartNew(() => { for(int i=0;i<1000;i++) bag.Add(i.ToString()); bag.Add("Last"); });
Task.Factory.StartNew(() => { foreach(var item in bag) Console.WriteLine(item); }).Wait();
IDisposable,支援 CompleteAdding() 標示完成。TryAdd/Take 多載接受逾時參數,避免無限等待。隨著並行運算普及,System.Collections.Concurrent 將成為日常開發核心工具,掌握其用法勢在必行。