2016-09-21 53 views
5

完成假設我有以下的回調:是否有當一個任務Task.WhenAll

IEnumerable<Task<TimeSpan>> tasks = //... 
TimeSpan[] results = await Task.WhenAll(tasks); 
// Handle results 

到時候我能處理所有的任務必須完成的結果。

有沒有辦法按需處理每個結果

就像註冊一個代表/回調當任務完成後,將得到執行:

IEnumerable<Task<TimeSpan>> tasks = //... 
await Task.WhenAll(tasks, result => 
{ 
    // A task has finished. This will get executed. 
    // result is of type TimeSpan 
}); 
+1

也許'任務[I] .ContinueWith()'? –

回答

4

有沒有一種方法來處理需求每個結果?

是的,你用WhenAny,而不是WhenAll ...或者每個任務調用ContinueWith

例如,對於WhenAny方法:

ISet<Task<TimeSpan>> tasks = new HashSet<Task<TimeSpan>>(...); 
while (tasks.Count != 0) 
{ 
    var task = await Task.WhenAny(tasks); 
    // Use task here 
    tasks.Remove(task); 
} 

還有就是你改造任務的原始序列爲任務的序列完成,以便另一種選擇,你可以使用,但是給了相同的結果。詳細信息可在this blog post,但結果是,你可以使用:

foreach (var task in tasks.InCompletionOrder()) 
{ 
    var result = await task; 
    // Use the result 
} 
+0

謝謝!我認爲我要用'ContinueWith'方法,因爲它看起來更清晰,更正確的語義 –

+0

@JonSkeet讓我們獲得一些聲譽:) –

+0

@MatiasCicero:兩者在語義上是正確的 - 它只取決於什麼結果是最簡單的。添加一個鏈接到另一個替代品... –

4

有沒有一種方法來處理需求每個結果?

就像註冊一個代表/回調當任務完成

是會得到執行,你只需要調整你的思考了一下。

忘記註冊回調(ContinueWith is a dangerous, extremely low-level API)。另外,你幾乎從不需要完成任務。相反,根據操作(任務)考慮您的問題。

現在,您擁有一組返回TimeSpan的任務。該集合中的每個項目都是一個返回TimeSpan的單個操作。你真正想要做的是引入一個高級操作的概念,它等待原始操作完成,然後執行你的操作後邏輯。

這正是async/await是:

private static async Task<TimeSpan> HandleResultAsync(Task<TimeSpan> operation) 
{ 
    var result = await operation; 
    // A task has finished. This will get executed. 
    // result is of type TimeSpan 
    ... 
    return result; // (assuming you want to propagate the result) 
} 

現在,你想這種更高級別的操作應用到您的現有業務。 LINQ的Select非常適合這樣的:

IEnumerable<Task<TimeSpan>> tasks = ... 
IEnumerable<Task<TimeSpan>> higherLevelTasks = tasks.Select(HandleResultAsync); 

TimeSpan[] results = await Task.WhenAll(higherLevelTasks); 
// By the time you get here, all results have been handled individually. 

如果您不需要結果的最終集合,這可以進一步簡化:

private static async Task HandleResultAsync(Task<TimeSpan> operation) 
{ 
    var result = await operation; 
    // A task has finished. This will get executed. 
    // result is of type TimeSpan 
    ... 
} 

IEnumerable<Task<TimeSpan>> tasks = ... 
IEnumerable<Task> higherLevelTasks = tasks.Select(HandleResultAsync); 
await Task.WhenAll(higherLevelTasks); 
+0

我真的很驚訝,因爲你使用了LINQ的'Select'。這是完美的! –

相關問題