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