我有以下示例:
public void Run()
{
var ctc = new CancellationTokenSource();
try
{
DoAsync(ctc).Wait();
Console.WriteLine("Done");
}
catch (AggregateException exception)
{
Console.WriteLine("Inside try-catch block");
Console.WriteLine();
Console.WriteLine(exception);
exception.Handle(ex =>
{
Console.WriteLine(ex.Message);
return true;
});
}
}
private async Task DoAsync(CancellationTokenSource ctc)
{
Console.WriteLine("DoAsync started");
await Task.Run(() =>
Console.WriteLine("DoAsync Run"),
ctc.Token
)
.ContinueWith(antecedent =>
Console.WriteLine("DoAsync Run cancelled"),
TaskContinuationOptions.OnlyOnCanceled
);
Console.WriteLine("DoAsync finished");
}
我已经创建了一个方法 (DoAsync),可以执行一些异步工作,并且可以在任何时候取消。如您所见,Task.Run获取了一个取消令牌。因此,我使用continuationOptions = TaskContinuationOptions.OnlyOnCanceled创建了连续任务。结果,我期望只有在请求取消时才调用连续任务,在其他情况下被忽略。但是在我的实现中,由ContinueWith返回的任务在其前置任务未被取消时会抛出异常:
DoAsync started
DoAsync Run
Inside try-catch block
System.AggregateException...
A task was canceled.
我可以通过添加另一个 ContinueWith 来修复这个问题,如下例所示:
await Task.Run(() =>
Console.WriteLine("DoAsync Run"),
ctc.Token
)
.ContinueWith(antecedent =>
Console.WriteLine("DoAsync Run cancelled"),
TaskContinuationOptions.OnlyOnCanceled
)
.ContinueWith(antecedent => { });
这段代码不会抛出任何异常。
但是我能够正确地使用单个ContinueWith处理取消吗?
catch (OperationCanceledException ex) when ex.CancellationToken.Equals(ctc.Token) { Console.WriteLine("DoAsync Run cancelled"); }
来重新创建它。 - Scott ChamberlainContinueWith
。在try
/catch
中使用await
会导致代码更易于维护。 - Stephen Cleary