Parallel.ForEach vs Task.Factory.StartNew

下面的代码片段有什么区别? 不会都使用线程池线程?

例如,如果我想调用集合中的每个项目的函数,

Parallel.ForEach<Item>(items, item => DoSomething(item)); vs foreach(var item in items) { Task.Factory.StartNew(() => DoSomething(item)); } 

第一个是更好的select。

在内部,Parallel.ForEach使用Partitioner<T>将您的集合分发到工作项目中。 每个项目不会执行一项任务,而是批量执行,以降低所涉及的开销。

第二个选项将为您的collections中的每个项目安排一个单独的Task 。 虽然结果会(几乎)相同,但是这会带来比必要的更多的开销,特别是对于大型集合,并导致整体运行时间变慢。

仅供参考 – 使用的分区程序可以通过对Parallel.ForEach使用适当的重载来控制,如果需要的话。 有关详细信息,请参阅MSDN上的自定义分区程序 。

主要的区别是,在运行时,第二个是asynchronous的。 这可以通过使用Parallel.ForEach来复制:

 Task.Factory.StartNew( () => Parallel.ForEach<Item>(items, item => DoSomething(item))); 

通过这样做,您仍然可以利用分区器,但在操作完成之前不会阻塞。

我做了一个小小的实验,用“Parallel.For”运行一个“10亿次”的方法,用“Task”对象运行一个方法。

我测量了处理器的时间,发现并行效率更高。 Parallel.For将您的任务分为小工作项目,并以最佳方式在所有核心上并行执行。 在创build大量任务对象(FYI TPL将在内部使用线程池)时,会移动每个任务的每个执行,从而在下面的实验中明显体现出更多的压力。

我还创build了一个小video,解释了基本的TPL,并演示了Parallel.For与正常的任务和线程相比如何更高效地利用您的内核http://www.youtube.com/watch?v=No7QqSc5cl8

实验1

 Parallel.For(0, 1000000000, x => Method1()); 

实验2

 for (int i = 0; i < 1000000000; i++) { Task o = new Task(Method1); o.Start(); } 

处理器时间比较

Parallel.ForEach会优化(甚至可能不会启动新线程)并阻塞,直到循环结束,Task.Factory将为每个项目显式创build一个新的任务实例,并在完成之前返回(asynchronous任务)。 Parallel.Foreach更高效。