.Net(C#) 线程安全阻塞集合 BlockingCollection 简要用法



BlockingCollection 自 .NET Framework 4.0 起提供,是线程安全的阻塞集合,适合在经典的“生产者-消费者”场景中使用。

下面介绍常用的属性和方法。


限制最大容量 BoundedCapacity

BoundedCapacity 可以设置集合最大容量,也可以在构造函数中直接传入。

BlockingCollection<T>(int boundedCapacity)


添加 Add(T item) / TryAdd(T item)

使用 Add 添加 item 时,如果集合已到最大容量,线程会被阻塞等待添加;使用 TryAdd 时则会返回 true / false 表示添加结果。


移除 Take() / TryTask(out T item)

类似前面的 Add,如果集合为空 Take 会被阻塞,而 TryTake 会返回 true / false 表示结果。


完成标记 CompleteAdding() 及 IsCompleted / IsAddingCompleted

IsCompleted / IsAddingCompleted 初始为 false。

调用 CompleteAdding() 方法后,IsAddingCompleted 变为 true,此时不可以再向集合添加元素(继续添加会触发异常)。

当 IsAddingCompleted == true 且集合为空时,IsCompleted 变为 true。


枚举 BlockingCollection / GetConsumingEnumerable

BlockingCollection 本身继承自 IEnumerable,所以本身可以被 foreach 枚举,且线程安全。但要注意此种方式返回的是该时间点集合的元素,且获得的元素不会在集合中被移除。

GetConsumingEnumerable 可以返回最近加入的元素,如果当前没有元素加入集合中,它会阻塞等待新添加的元素。

如果调用 CompleteAdding() 完成添加,表示之后不会有新元素加入集合。此时 GetConsumingEnumerable 迭代器会在处理完集合中元素后跳出循环(而不会再阻塞)。


参考资料

  1. BlockingCollection API文档
  2. .NET(C#):线程安全集合的阻塞BlockingCollection的使用

不得不说网上 C# 相关资料比较少,一开始怎么也找不到,甚至想自己写一个简陋的阻塞队列用。后来发现官方 API 文档很强大,耐心查询文档效率更高。❖