TPL 中的等待任务和 QueuedTaskScheduler 的令人不安的问题(来自 ParallelExtensio
本文关键字:问题 来自 令人不安 ParallelExtensio 等待 任务 TPL QueuedTaskScheduler | 更新日期: 2023-09-27 18:34:08
我在ParallelExetensionExtras附带的QueuedTaskScheduler上遇到了一个令人不安的问题,但我的问题对等待任务,任务调度器和线程资源相当笼统。
似乎等待任务会消耗资源,请先检查此示例,该示例使用默认任务计划程序,在此示例中,有一个任务运行很长时间,多个任务等待其完成,而下面还有其他任务等待执行。
这里一切正常,我可以看到这些等待任务开始工作,然后在等待期间释放资源,以便其他任务也开始执行。
var taskScheduler = TaskScheduler.Default;//ts.ActivateNewQueue(0);
var longRunningTask = Task.Factory.StartNew(() => Thread.Sleep(Int32.MaxValue), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() =>
{
Console.WriteLine("Hi from waiting task");
longRunningTask.Wait();
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() =>
{
Console.WriteLine("Hi from waiting task");
longRunningTask.Wait();
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() =>
{
Console.WriteLine("Hi from waiting task");
longRunningTask.Wait();
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler);
如果我更改前两行来执行此操作:
var ts = new QueuedTaskScheduler();
var taskScheduler = ts.ActivateNewQueue(0);
意思是,定义一个具有一个队列的 QueuedTaskScheduler 并运行相同的代码,其他任务永远不会获得要运行的资源。
我的问题是以前是否有人遇到过它,如果有人知道如何更改任务计划程序以释放等待任务的资源。
QueuedTaskScheduler
的行为符合设计。问题是它有一个固定的最大并发级别,默认情况下设置为 Environment.ProcessorCount
。
因此,假设您没有更改默认值,则在 4 核计算机上最多会有 4 个正在运行的任务。
要解决此问题,您可以在不同的调度程序上运行长时间运行的任务(理想情况下是支持 TaskCreationOptions.LongRunning
的调度程序,如Default
调度程序(,或者只设置最大并发级别,在极端情况下设置为最大值:
var ts = new QueuedTaskScheduler(TaskScheduler.Default, int.MaxValue);