2012-11-02 42 views
0

我創建並開始了許多任務。 其中一項任務可能會引發異常。如果發生這種情況,我需要停止所有的任務。當這些任務中的任何一個引發異常時如何取消一堆任務?

現在我只看到唯一的方法是將CancellationTokenSource傳遞給每個任務並在catch塊中調用Cancel()。

TPL是否以更通用的方式支持所需功能?

喜歡的東西:

Action<Task> onExceptionAction = t => cancellationTokenSource.Cancel(); 
var task = Task.WhenAnyThrows<MyException>(tasks, onExceptionAction); 

和任務被認爲是完成(或取消),如果沒有異常被拋出

+1

在我看來,取消支持是非常通用的。你只需要一個'CancellationTokenSource',你可以傳遞給所有的任務。你只需要在該標記上調用'Cancel'來取消所有使用它的任務。對我來說似乎很普通。 –

+0

好吧,沒關係,但如果你有一些任務生產者呢?您可以從中收到與關聯CancellationTokenSource相關的可取消任務。在這種情況下,您無法控制此任務中的異常處理。您可以使用通過CreateLinkedTokenSource方法調用創建的鏈接CTS來取消此任務。不過,您無法在任務中嵌入取消操作。是的,這個例子有點意味着合理。 –

回答

2

如果我理解正確的話,你要的是ContinueWith()TaskContinuationOptions.OnlyOnFaulted

所以,你的方法可能是這樣的:

void CancelWhenAnyFaults(IEnumerable<Task> tasks, CancellationTokenSource cts) 
{ 
    foreach (var task in tasks) 
     task.ContinueWith(
      _ => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, 
      TaskScheduler.Current); 
} 

我傳遞的CancellationTokenContinueWith()了,所以,當一個任務失敗,不執行其他的延續。

+0

爲什麼OnlyOnFaulted我會認爲NotOnFaulted或NotOnCancelled? – Paparazzi

+1

@Blam當'Task'發生故障時,你想做一些事情(取消令牌),這就是爲什麼'OnlyOnFaulted'。 – svick