繁体   English   中英

为什么使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM