2012-08-07 47 views
2

以下爲this question(及其答案)我想使用TaskCompletionSource和Task.WhenAll等到任何任務首先返回True。所以我寫了這一點:如何正確使用Task.WhenAll

TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); 
Task<bool> t0 = Task.Factory.StartNew<bool>(() => Find(paramA, paramB); 
Task<bool> t1 = Task.Factory.StartNew<bool>(() => Find(paramC, paramD); 
Task<bool> t2 = Task.Factory.StartNew<bool>(() => Find(paramE, paramF); 
Task<bool> t3 = Task.Factory.StartNew<bool>(() => Find(paramG, paramH); 

t0.ContinueWith(_ => 
{ 
    if (t0.Result) 
     tcs.TrySetResult(t0.Result); 
}); 

t1.ContinueWith(_ => 
{ 
    if (t1.Result) 
     tcs.TrySetResult(t1.Result); 
}); 

t2.ContinueWith(_ => 
{ 
    if (t2.Result) 
     tcs.TrySetResult(t2.Result); 
}); 

t3.ContinueWith(_ => 
{ 
    if (t3.Result) 
     tcs.TrySetResult(t3.Result); 
}); 

t4.ContinueWith(_ => 
{ 
    if (t4.Result) 
     tcs.TrySetResult(t4.Result); 
}); 

tcs.Task.Wait(); 
return tcs.Task.Result; 

它正常工作時,任何任務返回true,但正如先前答案注意到:

當所有任務都返回false ...中的棘手位被察覺 .NET 4.5,這將是相當容易的,由經 創建另一個任務Task.WhenAll

所以我試圖用Task.WhenAll玩,但我不希望使用它正確...
我想類似的東西:

tcs.Task.Wait(); // stays block here when all tasks return false 
Task tr = Task.WhenAll(new Task[] { t0, t1, t2, t3, t4 }); 

if (tr.IsCompleted) 
    return false; 
else 
return tcs.Task.Result; 

謝謝您的幫助

+0

和問題是什麼? :) – 2012-08-07 07:48:30

+0

如何使用Task.WhenAll獲得結果,即使所有任務返回false? – Florian 2012-08-07 07:50:59

回答

2

檢查結果時,它是false你可以使用

if (!task.Result) 
{ 
    // Do stuff... 
} 

這將檢查如果布爾結果爲假。要更完整,你可以做類似

asyncTask.ContinueWith(task => 
{ 
    // Check task status. 
    switch (task.Status) 
    { 
     case TaskStatus.RanToCompletion: 
      if (asyncTask.Result) 
      { 
       // returned true. 
      } 
      else 
      { 
       // returned false 
      } 
      break; 
     default: 
      break; 
    } 
} 

我希望這可以幫助。

5

你要等到你完成這兩個任務之一,這是Task.WaitAny()是什麼:

Task tr = Task.WhenAll(new Task[] { t0, t1, t2, t3, t4 }); 
Task.WaitAny(tcs.Task, tr); 

if (tcs.Task.IsCompleted) 
    return tcs.Task.Result; 

return false; 

這也是在你的代碼修復了一個競爭條件:tr.IsCompleted可能true,即使有些任務返回true,因爲所有的任務可以同時完成。

也可以使用Task.WhenAny(),如果您不想阻止。

但因爲你正在使用.NET 4.5,你不妨一起Interleaved() method, which orders the tasks as they complete使用await

async Task<bool> AnyTrue(IEnumerable<Task<bool>> tasks) 
{ 
    foreach(var bucket in Interleaved(tasks)) 
    { 
     if (await await bucket) 
      return true; 
    } 

    return false; 
} 
+0

Thx爲您的答案...我嘗試它! :) – Florian 2012-08-08 07:40:36