ThreadPool.QueueUserWorkItem 和 Parallel.ForEach 的区别?
Posted
技术标签:
【中文标题】ThreadPool.QueueUserWorkItem 和 Parallel.ForEach 的区别?【英文标题】:Difference between ThreadPool.QueueUserWorkItem and Parallel.ForEach? 【发布时间】:2013-02-13 21:21:03 【问题描述】:以下两种方法的主要区别是什么:
ThreadPool.QueueUserWorkItem
Clients objClient = new Clients();
List<Clients> objClientList = Clients.GetClientList();
foreach (var list in objClientList)
ThreadPool.QueueUserWorkItem(new WaitCallback(SendFilesToClient), list);
System.Threading.Tasks.Parallel ForEach
Clients objClient = new Clients();
List<Clients> objClientList = Clients.GetClientList();
Parallel.ForEach<Clients>(objClientList, list =>
SendFilesToClient(list);
);
我是多线程的新手,想知道每种情况下会发生什么(就执行过程而言)每种方法的多线程级别是多少?帮助我可视化这两个过程。
SendFilesToClient: 从数据库中获取数据,转换为 Excel 并将 Excel 文件发送到相应的客户端。
谢谢!
【问题讨论】:
【参考方案1】:主要区别在于功能。 Parallel.ForEach
将阻塞(按设计),因此在处理完所有对象之前它不会返回。您的foreach
排队线程池线程工作会将工作推送到后台线程,而不是阻塞。
此外,Parallel.ForEach
版本还有另一个主要优点 - 未处理的异常将被推回此处的调用站点,而不是在 ThreadPool 线程上未处理。
一般来说,Parallel.ForEach
会更有效率。这两个选项都使用 ThreadPool,但Parallel.ForEach
执行智能分区以防止线程过多并减少调度程序所需的开销。单个任务(将映射到 ThreadPool 线程)被重用,并有效地“池化”以降低开销,特别是如果 SendFilesToClient
是一个快速操作(在这种情况下不会是真的)。
请注意,作为第三种选择,您还可以使用 PLINQ:
objClientList.AsParallel().ForAll(SendFilesToClient);
这在性能和功能方面与Parallel.ForEach
方法非常相似。
【讨论】:
感谢@Reed 的详细解释。两个问题:1)为什么块很重要(如果您能回答我的代码,那就太好了)? 2) 进一步扩展主要问题,使用 PLINQ 而不是 Parallel.ForEach 有什么额外的好处吗? @Mihir 1) 阻塞是不同的。您正在运行的线程将等待 Parallel.ForEach 在运行下一行代码之前完成,但 foreach/TP.QUWI 代码不会等待。 2)没有优势,除了可能更容易理解的代码以上是关于ThreadPool.QueueUserWorkItem 和 Parallel.ForEach 的区别?的主要内容,如果未能解决你的问题,请参考以下文章