在 .NET 中按优先级安排任务

maf*_*afu 5 .net c# task-parallel-library

在.NET中,我想安排大量的Tasks,例如通过Task.Run(...). 有些任务的重要性较低,如果有较高优先级的任务可供执行,则调度程序应延迟这些任务。

有没有办法做到这一点?.NET 中似乎没有TaskScheduler支持任何优先级的调度。

这些任务是短期运行且无层级的。需要明确的是,这与执行任务的线程的优先级完全无关。

QueuedTaskScheduler来自ParallelExtensionsExtras似乎是我正在寻找的东西,但它已经七年没有维护了,缺乏文档,并且大多数与其相关的链接都已损坏 - 我宁愿不添加对它的依赖。

Joh*_* Wu 3

如果您想保持简单,请对操作而不是任务进行排队。由于我们正在排队异步调用,因此队列类型为Func<Task>。对于不同的优先级使用两个队列。

ConcurrentQueue<Func<Task>> _highPriorityQueue;
ConcurrentQueue<Func<Task>> _lowPriorityQueue;
Run Code Online (Sandbox Code Playgroud)

然后创建一个工作进程来按优先级顺序检查两个队列。

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后启动一些线程来处理队列:

var source = new CancellationTokenSource();
var threads = Enumerable.Range(0, numberOfThreads).Select( i =>
    Task.Run( () => WorkerProc(source.GetToken()) )
).ToList();
Run Code Online (Sandbox Code Playgroud)

并添加到队列:

_highPriorityQueue.Enqueue( () => Foo() );
_lowPriorityQueue.Enqueue( () => Bar() );
Run Code Online (Sandbox Code Playgroud)

去关机:

source.Cancel();
await Task.WhenAll( threads );
Run Code Online (Sandbox Code Playgroud)