首页 > 解决方案 > 为什么使用 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(),直到所有其他线程完成。

标签: c#.netmultithreading

解决方案


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.


推荐阅读