c# - 为什么使用 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()
,直到所有其他线程完成。
解决方案
It isn't inefficient, it is simply the way you have coded it. While parallel thread execution is useful, so is sequential execution. The main purpose for the Parallel.Foreach is to iterator over an enumeration by partitioning the enumeration across multiple threads. Lets say for example the Foreach loop calculates a value by applying operations to each item in the enumeration. You then want to use this single value in a call to doMoreWork. If the Foreach loop and the doMoreWork executed in parallel you would have to introduce some form of wait to ensure the foreach completed before calling doMoreWork.
You might want to take a look at the Task Class documentation and examples. If you really want to have a Parallel.Foreach and doMoreWork running in separate threads at the same time you can uses Task.Run to start a function (or lambda), then independently wait on these to finish.
I will note that parallel execution doesn't guarantee efficient or speed. There are many factors to consider such as Amdahl's law, the effect of locking memory to ensure coherence, total system resources, etc. It's a very big topic.
推荐阅读
- java - 基于来自另一个列表的值组合的流过滤器列表
- java - 如何避免插页式广告在关闭后重新加载
- php - 如何使用 php 和 mysql 执行多个 AND 运算符和 OR 运算符?
- sql - 如何选择每列最多一列
- java - 在 set(playerVal, scan.nextInt()) 中收到错误;
- c# - 找不到包 Microsoft.AspNetCore.Identity.EntityFramework
- java - android DatagramChannel 隧道必须连接到 VpnService 中的服务器?
- regex - 我正在寻找一种解决方案来了解特定单词或数字是否在行的最后,然后是空,甚至是空格
- c# - arcgis Map api 是否支持 UWP windows 应用程序中的集群位置?
- python-3.x - 如何从我的 Lambda 函数将变量传递给我的 SSM 运行命令文档