一个 List<BlockingCollection<T>> 是否线程安全?

8
我希望您能帮我翻译以下内容:

我想要维护一个包含多个BlockingCollections的列表。

List<BlockingCollection<ExtDocument>> a = new List<BlockingCollection<ExtDocument>>();

检查子线程中是否有任何“队列”仍有待处理的项目:

if (a.Where(x => x.IsAddingCompleted).Count > 0)

在这种情况下,如果列表中的项目数量在初始化后不会更改(集合内的阻塞列表的内容当然会更改),那么使用List<T>是否线程安全?或者我应该选择一个BlockingCollection数组或以下结构:
BlockingCollection<BlockingCollection<workitem>> a = new BlockingCollection<BlockingCollection<workitem>>();

7
如果列表在初始化后不会发生改变,那么直接使用列表是完全可以的。读取操作并不会对并发造成问题,而它的可变性最终才是问题所在。 - Caramiriel
6
我更倾向于使用数组而不是List<T>。这样可以更清晰地表明项目数量不会改变。 - CodesInChaos
@Caramiriel 谢谢你提供的信息!CodesInChaos:感谢你的提示。这确实会增加未来程序员的可读性。 - User999999
2
或者当您有能力使用.NET框架4.5时,可以使用IReadOnlyList<T>(顺便说一下,T[]继承了它)。 - Caramiriel
2
这可能有点过度,但你也可以研究一下不可变集合。也许是ImmutableList<T>或者ImmutableArray - Yuval Itzchakov
大量的好建议!谢谢你们! :) - User999999
1个回答

8

使用数组而不是List<T>的一个好处是,您可以使用BlockingCollection<T>.TakeFromAny等方法。很可能,您从错误的角度处理问题-然后您的处理线程只需执行BlockingCollection<T>.TryTakeFromAny,如果返回false,则完成了。完全线程安全,性能也相当不错。因此,您的处理循环将类似于以下内容:

while (BlockingCollection<ExtDocument>.TryTakeFromAny(collections, out workItem) >= 0)
{
  // Do work on workItem
}

// We're done!

确实非常好。一定在MSDN页面上阅读过了。马上测试一下! - User999999
确实比我迄今为止拥有的代码好多了。谢谢! - User999999

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接