简体   繁体   English

为什么使用Parallel.ForEach时主线程被阻塞

[英]why the primary thread is blocked when using Parallel.ForEach

Below is my code: 下面是我的代码:

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();
        ...
    }
}

so Parallel.ForEach fetches two threads from the ThreadPool plus existing primary thread. 因此Parallel.ForEach从ThreadPool以及现有的主线程中获取两个线程。 And the output is: 输出为:

Thread 1 is handling first 线程1首先处理

Thread 3 is handling second 线程3处理第二

Thread 4 is handling third 线程4正在处理第三项

and after 5 seconds: 5秒后:

Here is Thread 1 这是线程1

Obviously, thread 1(primary thread) was blocked. 显然,线程1(主线程)被阻塞。 But why wasbthe primary thread blocked? 但是,为什么主线程被阻塞了? I can kind of get the idea that primary thread is blocked to wait for other threads to finish their jobs. 我可以有点主线程被阻塞以等待其他线程完成其工作的想法。 But isn't that very inefficient, because the primary thread is blocked, it cannot continue to execute doMoreWork() until all other threads finish. 但这不是很低效,因为主线程被阻塞了,所以直到所有其他线程都完成后,它才能继续执行doMoreWork()

How else could this possibly work? 还有其他可能如何工作? The purpose of a parallel for loop is to speed up a calculation by performing parts of it in parallel. 并行for循环的目的是通过并行执行部分计算来加快计算速度。 The program cannot continue until all parts of the loop have completed (and the final result of the calculation can be computed). 该程序无法继续执行,直到循环的所有部分都已完成(并且可以计算出最终的计算结果)。 It's purpose is not to hand off work to execute asynchronously while the initiating thread continues on its way. 目的不是在启动线程继续前进的过程中交出异步执行的工作。 You're using the wrong tool for the job. 您为该工作使用了错误的工具。 You should look into Task objects. 您应该查看Task对象。

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. Parallel.Foreach的主要目的是通过在多个线程之间划分枚举来迭代枚举。 Lets say for example the Foreach loop calculates a value by applying operations to each item in the enumeration. 例如,让Foreach循环通过将操作应用于枚举中的每个项目来计算一个值。 You then want to use this single value in a call to doMoreWork. 然后,您要在对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. 如果并行执行Foreach循环和doMoreWork,则必须引入某种等待形式,以确保在调用doMoreWork之前完成foreach。

You might want to take a look at the Task Class documentation and examples. 您可能需要看一下Task Class文档和示例。 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. 如果您确实希望同时在单独的线程中运行Parallel.Foreach和doMoreWork,则可以使用Task.Run启动一个函数(或lambda),然后独立等待它们完成。

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. 有许多因素需要考虑,例如阿姆达尔定律 ,锁定内存以确保一致性的效果,系统总资源等。这是一个非常大的话题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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