TaskFactory.Tasks中BlockingCollection.GetConsumingEnumerable()集合的Parallel.ForEach和foreach循环 [英] Parallel.ForEach and foreach loops for BlockingCollection.GetConsumingEnumerable() collection in TaskFactory.Tasks

查看:137
本文介绍了TaskFactory.Tasks中BlockingCollection.GetConsumingEnumerable()集合的Parallel.ForEach和foreach循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have experimented with both of these loops and came to notice that even though regular foreach loop in Task's Action delegate supposed to perform in parallel, it doesn't process elements in parallel. However if i replace it with Parallel.ForEach i see data is being processed in parallel across multiple threads.

代码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确实并行处理多个元素.

Code 1 when run with Console.Write statement on each iteration seems to be waiting for the previous cycle to complete till it grabs next one, but Code 2 does process multiple elements in parallel.

我不正确理解Task.Action中的常规foreach吗?我以为.NET将按照负载保证启动尽可能多的线程,并且foreach的每次迭代都将并行处理.

Am i not understanding regular foreach in Task.Action correctly? I thought .NET would start as many threads for the task as load warrants and each iteration of foreach would be processed in parallel.

我也尝试过将PLINQ结果传递给上述两个代码,并且观察者具有相同的行为:即使我使用了.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism),常规的foreach似乎也等待上一次迭代完成以开始下一个迭代.指令.

I have also tried passing PLINQ result to both of the above codes and observer same behavior: regular foreach seemed to wait for the previous iteration to complete to start the next one, even though i have used .AsParallel() and .WithExecutionMode(ParallelExecutionMode.ForceParallelism) directives.

任何见识都将受到高度赞赏. 我知道OrderingPartitioner类,可以尝试使用它

Any insight would be highly appreciated. I am aware of OrderingPartitioner class and may try using it

推荐答案

常规的foreach总是 依次运行其迭代.在某些情况下,没有任何魔术可以将其变成并行构造.这就像把您扔进 pit ,因为那样很难断言像foreach循环这样简单的事物的正确性.幸运的是,C#的目标之一就是将您带入成功之路:

A regular foreach always runs its iterations sequentially. There is no magic that turns it into a parallel construct in some situations. That would be like throwing you into the pit of despair, because then it would be difficult to assert the correctness of something as simple as a foreach loop. Fortunately, one of the goals of C# is to throw you into the pit of success:

如果将foreach循环放在单独的任务上运行,则会使所有迭代顺序运行,但是您可以与整个foreach并行运行其他代码.

If you put a foreach loop running on a separate task, you get all the iterations running sequentially, but you can run other code in parallel with the entire foreach.

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

The flow of execution of a regular foreach on a separate task looks like this:

              |
            __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

希望能帮助您了解正在发生的事情.

Hope that helps understand what's happening.

这篇关于TaskFactory.Tasks中BlockingCollection.GetConsumingEnumerable()集合的Parallel.ForEach和foreach循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆