我可以在ConcurrentBag<Τ>上使用普通的foreach循环吗?

14
在我的代码的一个并行部分中,我将每个线程的结果保存到一个ConcurrentBag<Τ>中。然而,当这个过程完成后,我需要遍历这些结果,并将它们通过我的评估算法运行。普通的foreach循环是否能够遍历所有成员,还是需要特殊的代码?我也考虑过使用队列而不是背包,但我不知道哪个更好。背包通常在并行代码结束时只包含大约20个项目。
也就是说,foreach循环是否能够访问和运行ConcurrentBag<Τ>中的所有成员?
ConcurrentBag<Future> futures = new ConcurrentBag<Future>();
foreach (var move in futures)
{
    // stuff
}

1
由于它是IEnumerable,因此您应该能够在ConcurrentBag上使用foreach。 - Viru
我添加了示例代码。我问这个问题是因为使用 ConcurrentBag 时,不能保证你的项按照特定顺序输出。 - furrysalamander
1
我还需要看到您填充此ConcurrentBag的代码... ConcurrentBag已经被线程填充了吗?还是您计划在其他线程仍在更新ConcurrentBag时执行foreach操作? - Viru
并发包在填充后将被查看。此时只有一个线程会触及它。 - furrysalamander
2个回答

15

你不需要特殊的代码,C#的foreach将调用“GetEnumerator”,该方法会提供一个快照

枚举的项表示内容的瞬时快照。它不反映在调用GetEnumerator之后对集合进行的任何更新。


2

您可以在ConcurrentBag上使用普通的ForEach,但不会产生任何性能影响。

这类似于在List上使用ForEach。

为了获得更好的性能,请在ConcurrentBag上使用Parallel.Foreach。

Parallel.ForEach(futures,move=> doOperation;);

只有在需要执行多线程操作时,才使用ConcurrentBag。


Parallel.ForEach()并不能神奇地提供更好的性能。在许多常见情况下,Parallel.ForEach()实际上比foreach慢得多。 - svick
如果您正在使用大量数据,Parallel.ForEach将会非常快。 - Nambirajan S
我想阅读一些关于这个的文档。目前,我会尝试使用普通的foreach,因为在我的简单用例中,快照已经足够好了。 - Tore Aurstad

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