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

| 我已经对这两个循环进行了实验,发现即使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结果传递给上述代码,并且观察者具有相同的行为:即使我使用了
.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
指令,常规的foreach似乎也在等待上一个迭代完成以开始下一个迭代。 任何见解将不胜感激。 我知道OrderingPartitioner类,可以尝试使用它     
已邀请:
常规的foreach始终按顺序运行其迭代。在某些情况下,没有任何魔术可以将其变成并行构造。这就像让您陷入绝望之地,因为那样很难断言诸如foreach循环之类的简单事物的正确性。幸运的是,C#的目标之一就是将您带入成功之路: 如果将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
希望能帮助您了解正在发生的事情。     

要回复问题请先登录注册