繁体   English   中英

在 .NET 中优先安排任务

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

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