将Tasks
排队到 ThreadPool 时,代码依赖于默认TaskScheduler
来执行它们。在我的代码示例中,我可以看到7 Tasks
最大值在不同的线程上并行执行。
new Thread(() =>
{
while (true)
{
ThreadPool.GetAvailableThreads(out var wt, out var cpt);
Console.WriteLine($"WT:{wt} CPT:{cpt}");
Thread.Sleep(500);
}
}).Start();
var stopwatch = new Stopwatch();
stopwatch.Start();
var tasks = Enumerable.Range(0, 100).Select(async i => { await Task.Yield(); Thread.Sleep(10000); }).ToArray();
Task.WaitAll(tasks);
Console.WriteLine(stopwatch.Elapsed.TotalSeconds);
Console.ReadKey();
有没有办法强制调度程序在其他线程上启动更多Tasks
?或者是否有更多"慷慨"框架中的调度程序没有实现自定义程序?
修改
添加ThreadPool.SetMinThreads(100, X)
似乎可以解决问题,我假设等待释放线程,因此池认为它可以启动另一个,然后立即恢复。
默认情况下,最小线程数设置为系统上的处理器数。您可以使用SetMinThreads方法来增加最小线程数。但是,不必要地增加这些值可能会导致性能问题。如果太多任务同时启动,则所有任务可能看起来都很慢。在大多数情况下,线程池将使用自己的算法来分配线程,从而表现更好。将最小值降低到小于处理器数量也会影响性能。
从这里开始:https://msdn.microsoft.com/en-us/library/system.threading.threadpool.setminthreads(v=vs.110).aspx
我删除了AsParallel
因为它不相关而且似乎让读者感到困惑。
答案 0 :(得分:3)
有没有办法强制调度程序在其他线程上启动更多任务?
你不能拥有比拥有CPU核心更多的执行线程。这就是计算机的工作原理。如果你使用更多的线程,那么你的工作实际上将完成更慢,因为线程必须交换进出核心才能运行。
还是有更多的"慷慨的"框架中的调度程序没有实现自定义程序?
PLINQ已经过调整,可以最大限度地利用硬件。
如果将Thread.Sleep
调用替换为实际使用CPU的内容(例如while (true) ;
),然后在任务管理器中查看CPU使用情况,则可以自行查看。我的期望是PLINQ在这个例子中使用的7或8个线程都是你的机器可以处理的。
答案 1 :(得分:0)
试试这个:php
您可以设置工作线程数(第一个参数)。
答案 2 :(得分:0)
使用WithDegreeOfParallelism扩展程序:
Enumerable.Range(0, 100).AsParallel().WithDegreeOfParallelism(x).Select(...
答案 3 :(得分:0)
可以使用ThreadPool.SetMinThread
:
https://gist.github.com/JonCole/e65411214030f0d823cb#file-threadpool-md