[英]Schedule tasks with priority in .NET
在 .NET 中,我想安排大量的Task
,例如通过Task.Run(...)
。 某些任务的重要性较低,如果有更高优先级的任务可供执行,则调度程序应将其延迟。
有没有办法做到这一点? .NET 中似乎没有TaskScheduler
支持任何优先级的调度。
这些任务是短期运行的且不分等级的。 需要明确的是,这与执行任务的线程的优先级完全无关。
来自ParallelExtensionsExtras 的QueuedTaskScheduler
似乎是我正在寻找的东西,但它已经七年没有维护了,缺乏文档,而且大部分与它相关的链接都已损坏 - 我宁愿不添加对它的依赖。
如果您想保持简单,请将操作而不是任务排队。 由于我们正在排队异步调用,因此队列类型为Func<Task>
。 对不同的优先级使用两个队列。
ConcurrentQueue<Func<Task>> _highPriorityQueue;
ConcurrentQueue<Func<Task>> _lowPriorityQueue;
然后创建一个工作进程以按优先级顺序检查两个队列。
async Task WorkerProc(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
Func<Task> action;
if (_highPriorityQueue.TryDequeue(out action))
{
await action();
continue;
}
if (_lowPriorityQueue.TryDequeue(out action))
{
await action();
continue;
}
await Task.Yield();
}
}
然后启动一些线程来处理队列:
var source = new CancellationTokenSource();
var threads = Enumerable.Range(0, numberOfThreads).Select( i =>
Task.Run( () => WorkerProc(source.GetToken()) )
).ToList();
并添加到队列中:
_highPriorityQueue.Enqueue( () => Foo() );
_lowPriorityQueue.Enqueue( () => Bar() );
去关机:
source.Cancel();
await Task.WhenAll( threads );
@John Wu 在只有 2 个优先事项的情况下,为这个案例提供了一个很好而简单的答案。
当需要更细粒度的优先级和可能的优先级更改(例如提高优先级)时,可以实现自己的基于优先级的队列。 为此,可以使用一些已排序或可排序的列表,例如SortedList<TKey,TValue>
。
对于键,我建议从优先级(作为主要)和调度时间(作为次要)构建一些东西。 小心使键唯一。
要非常小心地从列表中添加和删除任务线程安全(如果列表没有提供,您将需要自己实现线程安全)。
最后一些迭代:WorkerProc 看起来非常相似,只有一个任务列表(而不是 taks 队列),添加和删除任务而不是入队和出队。 任务将通过构建密钥将自己分类到正确的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.