我已经尝试过这两个循环,并发现即使在Task的Action委托中的常规foreach循环应该并行执行,它也不会并行处理元素。但是,如果我用Parallel.ForEach替换它,我看到跨多个线程并行处理数据。Parallel.ForEach和Foreach循环的TaskFactory.Tasks中BlockingCollection.GetConsumingEnumerable()集合
代码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);
});
});
代码1时Console.Write声明运行在每次迭代似乎在等待前一个周期完成下一个,直到它抓住一个,但Code 2并行处理多个元素。
我是不是无法正确理解Task.Action中的常规foreach?我认为.NET会像负载保证一样为任务启动多个线程,并且每个foreach迭代将被并行处理。
我也试过将PLINQ结果传递给上面的代码和观察者的相同行为:即使我已经使用了.AsParallel()
和.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
指令,常规foreach似乎等待先前的迭代完成以启动下一个代码。
任何有识之士将不胜感激。 我知道OrderingPartitioner类,并可能尝试使用它
“尽管Task's Action委托中的常规foreach循环应该并行执行”您是从哪里得到这个想法的? **一个普通的foreach是一个普通的foreach **。没有花哨的东西在里面。这就是为什么我们有'Parallel.ForEach()'。 – 2011-04-17 16:10:28
我已经比较了Task的Action委托和线性过程中的常规foreach性能。内部任务的动作委托它执行得更快,所以我认为threadpool正在决定要产生多少个并行线程来执行最佳任务。 – Dimitri 2011-04-17 16:15:28
有多快?我敢打赌,这是纯粹的运气或糟糕的基准。在任务内运行foreach仍然按顺序运行它,因为它仍然是一个foreach。 **没有魔法**。你可以做的是与* sequential * foreach并行运行。 – 2011-04-17 16:16:19