【问题标题】:Schedule tasks with priority in .NET在 .NET 中安排具有优先级的任务
【发布时间】:2020-02-22 09:03:41
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您是否考虑过编写自己的 SynchronizationContext?见this linkthis link
  • @JohnWu 似乎有点难以做到正确,但我会调查一下

标签: c# .net task-parallel-library


【解决方案1】:

如果您想保持简单,请排队执行操作而不是任务。由于我们正在排队异步调用,因此队列类型为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 );

【讨论】:

  • 我所做的与此非常接近 :) 虽然这种方法对我很有效,但它不能回答更普遍的问题,所以如果你不这样做,我不会将其标记为解决方案不介意。
  • while (true) { await Task.Yield(); } 对我来说就像一个紧密的循环。相当可怕的 CPU 资源浪费。
【解决方案2】:

@John Wu 对该案例给出了一个简单而简单的答案,当时只有 2 个优先级。

当需要更精细的优先级,并且可能需要更改优先级(例如提高优先级)时,可以实现自己的基于优先级的队列。为此,可以使用一些已排序或可排序的列表,例如SortedList&lt;TKey,TValue&gt;

对于键,我建议从优先级(作为主要)和调度时间(作为次要)构建一些东西。小心使键唯一。

要非常小心地确保从列表中添加和删除任务是线程安全的(如果列表没有提供线程安全,您需要自己实现线程安全)。

最后进行一些迭代:WorkerProc 看起来非常相似,只有一个任务列表(而不是 taks 队列),添加和删除任务而不是入队和出队。通过构造键,任务将自行排序到正确的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-15
    • 2011-05-26
    • 2021-04-29
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    相关资源
    最近更新 更多