是ConcurrentBag中的Parallel.ForEach <t>线程安全</t>

时间:2011-07-08 20:09:34

标签: multithreading c#-4.0 .net-4.0 concurrency thread-safety

MSDN上ConcurrentBag的描述不明确:

当订购无关紧要时,袋子对于存储物品很有用,而且与套装不同,袋子支持重复。 ConcurrentBag是一个线程安全的包实现,针对同一个线程生成和使用存储在包中的数据的情况进行了优化。

我的问题是线程安全,如果在Parallel.ForEach中使用ConcurrentBag是一个好习惯。

For Instance:

    private List<XYZ> MyMethod(List<MyData> myData)
    {
        var data = new ConcurrentBag<XYZ>();

        Parallel.ForEach(myData, item =>
                        {
                            // Some data manipulation

                            data.Add(new XYZ(/* constructor parameters */);
                        });

        return data.ToList();
    }

这样我就不必使用常规List在Parallel.ForEach中使用同步锁定。

非常感谢。

2 个答案:

答案 0 :(得分:8)

这对我来说很好看。你使用它的方式是线程安全的。

如果您可以返回IEnumerable<XYZ>,那么在完成后不复制到List<T>可以提高效率。

答案 1 :(得分:0)

ConcurrentBag和Parallel.ForEach在我看来,没问题。如果在具有大量多用户访问权限的方案中使用此类型,则实现中的这些类可能会将cpu进程升级到可能导致Web服务器崩溃的级别。此外,这个实现启动N个任务(线程)来执行每个迭代,所以在选择这个类和实现时要小心。我最近在这种情况下花了我不得不提取内存转储来分析我的Web应用程序核心发生了什么。所以,要小心'因为Concurrentbag是ThreadSafe,而在Web场景中,这是没有更好的方法。