c# - 为什么在使用 Parallel.ForEach 时主线程被阻塞

标签 c# .net multithreading

下面是我的代码:

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/

相关文章:

c# - WinForms donut 和饼图标签背景元素颜色属性

javascript - 我需要在 asp 链接按钮上显示表格行

c# - 查看结果或操作结果 |如果 ActionResult 无论如何都对一切都有好处,那么使用 ViewResult 是否有意义?

c# - 单个 "lock"或单独的读写器锁用于 IO 操作?

c - 从多个线程写入一个数组

java - 此类代码中是否存在线程安全错误?

c# - jquery发布错误500

c# - 托管 WinRT API 是否包括计算 MD5 哈希的方法?

c# - 在调试上下文列表中表示内容的更好方法?

Java 在自己的线程中绘制图形,在 EDT 之外?