12

我正在使用 Parallel.Foreach 来填充外部 ConcurrentBag。我也尝试使用一个通用列表,一切正常。

我是幸运还是错过了 ConcurrentBag 的特殊范围?

4

3 回答 3

18

你很幸运;Parallel.ForEach填充 List 不是线程安全的,您最终会遇到问题。

根据 MSDN,List<T>不是线程安全的:

不保证任何实例成员都是线程安全的。

只要不修改集合,List<T> 就可以同时支持多个读取器。通过集合进行枚举本质上不是线程安全的过程。在枚举与一个或多个写访问竞争的极少数情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。要允许集合被多个线程访问以进行读写,您必须实现自己的同步。

ConcurrentBag 是您应该使用的,它对于多个读取器和写入器是线程安全的。

于 2011-08-25T16:13:36.583 回答
5

如果您Parallel.ForEach用来填充 aList<T>并且一切正常,那么您只是走运了。该ForEach方法可以并且将在多个线程上运行您的代码,因此外部的任何通信都ForEach必须与可以处理并发更新的对象进行。 List<T>不能但ConcurrentBag<T>可以。

于 2011-08-25T16:13:17.730 回答
2

ConcurrentBag 是正确的答案,仅在 .NET 4.0 中它非常慢。这已在 .NET 4.5 中修复。见http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0

ConcurrentStack 和 ConcurrentQueue 也适用于您的情况......

于 2012-07-20T11:52:04.220 回答