.net并行和串行循环

本文关键字:循环 并行 net | 更新日期: 2023-09-27 18:27:26

我们希望围绕解决方案中的某些循环构建一个模式,允许它们根据因素以串行或并行方式运行。以下是它的一般形式。

由于并发集合与常规集合不共享一个公共接口,我们需要某种适配器来编写通用代码。

特别是关于循环体中addFunc委托的使用,是否有任何东西会导致我们可能错过的长期问题?到目前为止运行良好,但是。。。。?

Action<SomeType> addFunc;
if(runInParallel)
{
   addFunc = concurrentBag.Add;
   loopDelegate = Parallel.ForEach;
}
else
{
   addFunc = iList.Add;
   loopDelegate = Serial.ForEach; // wrapper delegate for foreach
}
loopDelegate(source, item =>
{
   SomeType result = longRunningTask(item);
   ...
   addFunc(result); // will this 
});

.net并行和串行循环

好奇为什么不在.NET 4.0中使用TPL?http://msdn.microsoft.com/en-us/library/dd537609.aspx

有一份很好的白皮书,介绍了他们在开发TPL时所考虑的问题,如果你不能使用.NET4,你应该看看这篇论文,并考虑其中的一些问题。

更新基于指出显而易见之处的评论。

我会用一些句法糖,比如

ForEach<Tsource>(Predicate<IEnumerable<TSource>> isParallel, IEnumerable<TSource> source, Action<TSource> body)
{
    if(isParallel(source))
    {
        Parallel.ForEach<TSource>(source, body);
    }
    else
    {
        foreach (TSource element in source)
        {
            body(element);
        }
    }
}

与您的实现相比,有两个主要优势。

  1. 您枚举两次,一次是添加要循环的项,第二次是在执行期间
  2. 这并不明显,但您正在停止Parallel.ForEach和ForEach使用最有效的getter。Parallel.ForeEach不会总是在IEnumerable中使用GetEnumerator。枚举器在设计上是不并发的,如果您的项实现了IList,Parallel.ForEach将使用索引器允许每个线程访问源中的元素,而无需等待枚举器遍历列表。ConcurrentBag未实现IList

这是我提到的论文,顺便说一句,http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=19222.

如果你在重复这篇文章,这是一本非常好的读物,但要特别注意,第1页[5-7]、第26页、第3页[0-2]。

句法糖意味着你可以像对待TPL、那样称呼它

MyParllelLibrary.ForEach( (list) => true, list), item =>
{
    // What my code does
});