我正在使用Parallel。Foreach用于填充外部ConcurrentBag。我也试着使用一个通用的列表,一切都很好。
我很幸运还是我错过了ConcurrentBag的特殊作用域?
你很幸运;Parallel.ForEach
填充List不是线程安全的,你最终会遇到问题。
List<T>
不是线程安全的:
不能保证任何实例成员都是线程安全的。
List
可以支持多个读机并发,只要不修改集合。枚举一个集合是本质上不是线程安全的过程。在极少数情况下枚举竞争一个或多个写访问,唯一的方法是确保线程安全是在整个收集过程中锁定的枚举。允许多个对象访问集合用于读写的线程,必须自己实现同步。
ConcurrentBag是你应该使用的,它对于多个读取器和写入器是线程安全的。
如果你使用Parallel.ForEach
来填充List<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也可以在你的情况下工作…