![](/img/trans.png)
[英]How to unblock “primary” thread for UI in winforms (using Parallel.Foreach)?
[英]why the primary thread is blocked when using Parallel.ForEach
下面是我的代码:
class Program
{
static void Main(string[] args)
{
Test();
}
static void Test()
{
string[] strList = { "first", "second", "third" };
Parallel.ForEach(strList, currStr =>
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is handling {currStr}");
if (Thread.CurrentThread.ManagedThreadId != 1) //if not primary thread, sleep for 5 secs
{
Thread.Sleep(5000);
}
});
Console.WriteLine($"Here is thread {Thread.CurrentThread.ManagedThreadId}");
...
doMoreWork();
...
}
}
因此Parallel.ForEach
从ThreadPool以及现有的主线程中获取两个线程。 输出为:
线程1首先处理
线程3处理第二
线程4正在处理第三项
5秒后:
这是线程1
显然,线程1(主线程)被阻塞。 但是,为什么主线程被阻塞了? 我可以有点主线程被阻塞以等待其他线程完成其工作的想法。 但这不是很低效,因为主线程被阻塞了,所以直到所有其他线程都完成后,它才能继续执行doMoreWork()
。
还有其他可能如何工作? 并行for循环的目的是通过并行执行部分计算来加快计算速度。 该程序无法继续执行,直到循环的所有部分都已完成(并且可以计算出最终的计算结果)。 目的不是在启动线程继续前进的过程中交出异步执行的工作。 您为该工作使用了错误的工具。 您应该查看Task
对象。
它不是低效的,它只是您编码的方式。 虽然并行线程执行很有用,但顺序执行也很有用。 Parallel.Foreach的主要目的是通过在多个线程之间划分枚举来迭代枚举。 例如,让Foreach循环通过将操作应用于枚举中的每个项目来计算一个值。 然后,您要在对doMoreWork的调用中使用此单个值。 如果并行执行Foreach循环和doMoreWork,则必须引入某种等待形式,以确保在调用doMoreWork之前完成foreach。
您可能需要看一下Task Class文档和示例。 如果您确实希望同时在单独的线程中运行Parallel.Foreach和doMoreWork,则可以使用Task.Run启动一个函数(或lambda),然后独立等待它们完成。
我将注意到并行执行不能保证效率或速度。 有许多因素需要考虑,例如阿姆达尔定律 ,锁定内存以确保一致性的效果,系统总资源等。这是一个非常大的话题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.