如果您使用的是async
/await
,則不需要另一個線程(因爲您沒有CPU綁定處理)。
就你而言,這聽起來像你只需要一個異步委託隊列。異步委託的自然類型是Func<Task>
(沒有返回值)或Func<Task<T>>
(具有返回值)。不幸的是,這個小技巧在這一點上並不爲人所知。
因此,申報異步委託隊列:
private readonly Queue<Func<Task>> queue = new Queue<Func<Task>>();
然後你就可以有一個單一的「頂級」的任務,只是(異步)處理隊列:
private Task queueProcessor;
的queueProcessor
只要沒有更多的物品,可以是null
。只要它不是null
,它會代表這個方法:然後
private async Task ProcessQueue()
{
try
{
while (queue.Count != 0)
{
Func<Task> command = queue.Dequeue();
try
{
await command();
}
catch (Exception ex)
{
// Exceptions from your queued tasks will end up here.
throw;
}
}
}
finally
{
queueProcessor = null;
}
}
你Enqueue
方法是這樣的:現在
private void Enqueue(Func<Task> command)
{
queue.Enqueue(command);
if (queueProcessor == null)
queueProcessor = ProcessQueue();
}
,我有異常處理設置是這樣的:任何排隊拋出異常的命令將導致隊列處理器停止處理(具有相同的異常)。這可能不是您的應用程序的最佳行爲。
您可以使用這樣的(帶有一個lambda或實際的方法,當然):
Enqueue(async() =>
{
ShowProgressIndicator = true;
ModelData = await myProxy.DownloadStringTaskAsync();
ShowProgressIndicator = false;
});
注意使用DownloadStringTaskAsync
。如果你write TAP wrappers for your EAP members,你的async
代碼將更「自然」(即更簡單)。
這是非常複雜,我建議你把它變成一個單獨的類,但你要決定如何處理(和麪)錯誤第一。
'BlockingCollection'? – I4V