我正在使用 Parallel.Foreach 来填充外部 ConcurrentBag。我也尝试使用一个通用列表,一切正常。
我是幸运还是错过了 ConcurrentBag 的特殊范围?
我正在使用 Parallel.Foreach 来填充外部 ConcurrentBag。我也尝试使用一个通用列表,一切正常。
我是幸运还是错过了 ConcurrentBag 的特殊范围?
你很幸运;Parallel.ForEach
填充 List 不是线程安全的,您最终会遇到问题。
根据 MSDN,List<T>
不是线程安全的:
不保证任何实例成员都是线程安全的。
只要不修改集合,List<T> 就可以同时支持多个读取器。通过集合进行枚举本质上不是线程安全的过程。在枚举与一个或多个写访问竞争的极少数情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。要允许集合被多个线程访问以进行读写,您必须实现自己的同步。
ConcurrentBag 是您应该使用的,它对于多个读取器和写入器是线程安全的。
如果您Parallel.ForEach
用来填充 aList<T>
并且一切正常,那么您只是走运了。该ForEach
方法可以并且将在多个线程上运行您的代码,因此外部的任何通信都ForEach
必须与可以处理并发更新的对象进行。 List<T>
不能但ConcurrentBag<T>
可以。
ConcurrentBag 是正确的答案,仅在 .NET 4.0 中它非常慢。这已在 .NET 4.5 中修复。见http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0
ConcurrentStack 和 ConcurrentQueue 也适用于您的情况......