TaskFactory.Tasks中BlockingCollection.GetConsumingEnumerable()集合的Parallel.ForEach和foreach循环

时间:2011-04-17 16:08:38

标签: c# multithreading parallel-processing task-parallel-library

我已经尝试了这两个循环,并注意到即使Task的Action委托中的常规foreach循环应该并行执行,它也不会并行处理元素。但是,如果我用Parallel.ForEach替换它,我会看到数据正在多个线程中并行处理。

代码1:

Task loadingTask1 = Factory.StartNew(() =>
        {
            foreach (MyOneClass dg in Queue.GetConsumingEnumerable())
            {

                MyOtherClass vl = new MyOtherClass();
                vl.Id = dg.Id;
                vl.PerformTimeConsumingAction();

                OutputQueue.Add(vl);
            }
        });

代码2:

Task loadingTask2 = Factory.StartNew(() =>
        {
            Parallel.ForEach(Queue.GetConsumingEnumerable(), (dg) =>
            {

                MyOtherClass vl = new MyOtherClass();
                vl.Id = dg.Id;
                vl.PerformTimeConsumingAction();

                OutputQueue.Add(vl);
            });
        });

在每次迭代时使用Console.Write语句运行时的代码1似乎等待上一个循环完成,直到它抓住下一个循环,但代码2确实并行处理多个元素。

我是否正确理解Task.Action中的常规foreach?我认为.NET会启动尽可能多的任务线程作为加载权证,并且每个foreach的迭代都将被并行处理。

我还尝试将PLINQ结果传递给上述两个代码和观察者相同的行为:常规foreach似乎等待上一次迭代完成以启动下一个迭代,即使我使用了.AsParallel()和{ {1}}指令。

任何见解都将受到高度赞赏。 我知道OrderingPartitioner类,可能会尝试使用它

1 个答案:

答案 0 :(得分:18)

常规foreach 始终按顺序运行其迭代。在某些情况下,没有魔法可以将它变成并行构造。这就像把你扔进pit of despair,因为那样就很难断言像foreach循环一样简单的东西的正确性。幸运的是,C#的目标之一就是让你陷入成功之中:

C# throwing you into the pit of success

如果你在一个单独的任务上运行foreach循环,你会顺序运行所有迭代,但是你可以与整个foreach并行运行其他代码。

在单独的任务上执行常规foreach的流程如下所示:

              |
            __v_
           /    \
other code |    | foreach iteration 1
other code |    | foreach iteration 2
other code |    | foreach iteration 3
           ......
other code |    | foreach iteration n-1
other code |    | foreach iteration n
           v    v

Parallel.Foreach的执行流程如下:

                  |
 _________________v________________
/    /    /    /    \    \    \    \
|1   |2   |3   |....|    |n-2 |n-1 |n
\____\____\____\____/____/____/____/
                  |
                  v

希望有助于了解正在发生的事情。