繁体   English   中英

Parallel.ForEach不使用所有可用的线程池线程

[英]Parallel.ForEach doesn't make use of all available thread pool threads

为什么当我运行以下示例时,我是否只让Parallel.ForEach运行的线程数等于我机器上的核心数? 我以为Parallel.ForEach给你的线程池线程大约有1000个?

            int threads1;
            int threads2;

            ThreadPool.GetAvailableThreads(out threads1,out threads2);
            var list = Enumerable.Range(1, 200);
            var po = new ParallelOptions
            {
                MaxDegreeOfParallelism = 100
            };

            Parallel.ForEach(list, po, x =>
                {
                    Console.WriteLine("Thread:" + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(1000);
                });

我在这里错过了什么吗?

Parallel.ForEach使用托管线程池来调度并行操作。 线程数由ThreadPool.SetMinThreadsThreadPool.SetMaxThreads设置。 默认情况下,最小线程数设置为系统上的处理器数。

为了最小化系统资源的使用,池线程的数量保持尽可能低。 当所有池线程忙于执行操作时,调度程序会逐渐生成新线程。

MaxDegreeOfParallelism值通常用于防止Parallel.For调度超过指定数量的任务。 在长计算的情况下,当没有使用比核心数更多的线程的意义时,它是有用的。

如果通过增加休眠时间Thread.Sleep(100000);修改代码Thread.Sleep(100000); ,您将看到新线程的创建。

如果你调用ThreadPool.SetMinThreads(100, 100); Parallel.ForEach之前,您将看到所有100操作同时启动。

如果线程数不超过处理核心数,您将获得最佳性能。

每个核心一次只能处理一个线程。 如果除了核心更多线程,操作系统必须切换线程之间。 上下文切换是一项昂贵的操作,您应该尽量避免在多线程应用程序中使用它。

如果您执行的操作是IO绑定的,则应使用Task而不是Paraller.For 斯科特汉塞尔曼的博客很好地解释了这一点。

Parallel.For线程管理的细节在Andrey Nasonov的回答中有详细解释,所以我不再重复了。

如果你想了解更多关于线程,TPL和异步I / OI推荐CLR通过C#book

暂无
暂无

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

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