下面是我的代码:
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()
。
答案 0 :(得分:3)
这怎么可能呢?并行for循环的目的是通过并行执行部分计算来加快计算速度。该程序无法继续执行,直到循环的所有部分都已完成(并且可以计算出最终的计算结果)。目的是 not 在启动线程继续前进的过程中将工作交还异步执行。您为该工作使用了错误的工具。您应该查看Task
个对象。
答案 1 :(得分:3)
这并不是低效率的,它只是您编写代码的方式。虽然并行线程执行很有用,但顺序执行也很有用。 Parallel.Foreach的主要目的是通过在多个线程之间划分枚举来迭代枚举。例如,让Foreach循环通过将操作应用于枚举中的每个项目来计算一个值。然后,您要在对doMoreWork的调用中使用此单个值。如果并行执行Foreach循环和doMoreWork,则必须引入某种等待形式,以确保在调用doMoreWork之前完成foreach。
您可能想看一下Task Class文档和示例。如果您确实希望同时在单独的线程中运行Parallel.Foreach和doMoreWork,则可以使用Task.Run启动一个函数(或lambda),然后独立等待它们完成。
我将注意到并行执行不能保证效率或速度。有许多因素需要考虑,例如Amdahl's law,锁定内存以确保一致性的效果,系统总资源等。这是一个非常大的话题。