下面是我的代码:
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 中获取两个线程加上现有的主线程。输出是:
Thread 1 is handling first
Thread 3 is handling second
Thread 4 is handling third
5 秒后:
Here is Thread 1
很明显,线程 1(主线程)被阻塞了。但是为什么主线程被阻塞了呢?我可以理解主线程被阻塞以等待其他线程完成它们的工作。但这不是很低效吗,因为主线程被阻塞,它无法继续执行 doMoreWork()
直到所有其他线程完成。
最佳答案
它并不低效,它只是您编码的方式。虽然并行线程执行很有用,但顺序执行也很有用。 Parallel.Foreach 的主要目的是通过跨多个线程对枚举进行分区来迭代枚举。比方说,Foreach 循环通过对枚举中的每个项目应用操作来计算一个值。然后您希望在对 doMoreWork 的调用中使用这个单一值。如果 Foreach 循环和 doMoreWork 并行执行,则必须引入某种形式的等待以确保 foreach 在调用 doMoreWork 之前完成。
您可能想看一下 Task Class文档和示例。如果你真的想让 Parallel.Foreach 和 doMoreWork 同时在不同的线程中运行,你可以使用 Task.Run 来启动一个函数(或 lambda),然后独立地等待它们完成。
我会注意到并行执行并不能保证效率或速度。有很多因素需要考虑,例如 Amdahl's law ,锁定内存以确保一致性的效果,系统资源总量等。这是一个非常大的话题。
关于c# - 为什么在使用 Parallel.ForEach 时主线程被阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56783072/