簡體   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