[英]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.SetMinThreads
和ThreadPool.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.