我有以下代碼,其中Task
可以被取消,但我基本上需要等待它完成(以確保完整性),然後將OperationCanceledException
扔給調用者。等待取消的任務在繼續執行之前完成
public static void TaskCancellationTest() {
try {
Console.WriteLine("TaskCancellationTest started.");
var cts = new CancellationTokenSource();
var t = Task.Run(() => {
if (cts.Token.IsCancellationRequested) return;
Console.WriteLine("1");
Task.Delay(2000).Wait();
Console.WriteLine("2");
}).ContinueWith(task => {
if (cts.Token.IsCancellationRequested) return;
Console.WriteLine("3");
Task.Delay(2000).Wait();
Console.WriteLine("4");
});
Task.Run(() => {
Task.Delay(1000).Wait();
Console.WriteLine("Cancelling...");
cts.Cancel();
});
t.Wait();
try {
cts.Token.ThrowIfCancellationRequested();
}
catch (OperationCanceledException) {
Console.WriteLine("Gracefully canceled.");
}
Console.WriteLine("TaskCancellationTest completed.");
}
catch (Exception ex) {
Console.WriteLine("TaskCancellationTest... Failure: " + ex);
}
}
結果如市場預期,是:
1
Cancelling...
2
Gracefully canceled.
它的工作原理,但我寧願到CancellationToken
傳遞給方法,因爲我明白這是一個更好的模式。我還希望能夠觀察方法體內的令牌,並呼叫ThrowIfCancellationRequested()
放棄而不必等待下一個ContinueWith(
)。
我正在玩下面的替代代碼,這也適用,但有沒有辦法讓OperationCanceledException
而不是AggregateException
?
如果我通過的CancellationToken到WaitAll()
方法,問題是,它會在令牌的消除立即拋出OperationCanceledException
,而不是等待的任務t1
和t2
實際完成(他們將繼續在後臺運行)然後只拋出異常。
public static void TaskCancellationTest2() {
try {
Console.WriteLine("TaskCancellationTest2 started.");
var cts = new CancellationTokenSource();
var t1 = Task.Run(() => {
Console.WriteLine("1");
Task.Delay(2000).Wait();
Console.WriteLine("2");
}, cts.Token);
var t2 = t1.ContinueWith(task => {
Console.WriteLine("3");
Task.Delay(2000).Wait();
cts.Token.ThrowIfCancellationRequested();
Console.WriteLine("4");
}, cts.Token);
Task.Run(() => {
Task.Delay(1000).Wait();
Console.WriteLine("Cancelling...");
cts.Cancel();
});
try {
try {
Task.WaitAll(t1, t2);
}
catch (AggregateException ae) {
if (ae.InnerExceptions.Count == 1 && ae.InnerExceptions.Single() is OperationCanceledException) {
throw ae.InnerExceptions.Single();
}
throw;
}
}
catch (OperationCanceledException) {
Console.WriteLine("Gracefully canceled.");
}
Console.WriteLine("TaskCancellationTest2 completed.");
}
catch (Exception ex) {
Console.WriteLine("TaskCancellationTest2... Failure: " + ex);
}
}
我準備了一把小提琴here。
This question的標題與我的非常相似,但是接受的答案不幸與我的情況無關。
你知道有什麼方法可以達到我想要的效果嗎?儘量使用CancellationToken
?
如果我不叫't.Wait()','然後Console.WriteLine( 「2」);'會後'TaskCancellationTestNotWorking異步執行( )'會返回。這是我需要避免的(如果我正在編寫文件而不是寫入「2」,則需要確保TaskCancellationTestNotWorking()不會在文件寫入操作完成之前返回)。 – 2014-08-28 04:49:27
如果任務處於「已取消」狀態,則「IsCompleted」將返回true,儘管它仍可能正在執行代碼。 – 2014-08-28 04:51:12
你已經調用了'Wait()'並且它拋出了一個異常,你爲什麼要再次調用它? – 2014-08-28 06:08:24