在什么情况下等待已取消的任务会引发任务已取消异常?



我习惯于在处理异步操作的取消时能够执行异步模式:

public async Task InvokeAsync(CancellationToken cancellationToken)
{
using(cancellationToken.Register(handler.Stop))
{
try
{
await handler.HandleAsync();
}
catch(HandlerStoppedException ex)
{
cancellationToken.ThrowIfCancellationRequested();
throw;
}
}
}

该方法调用公开某种取消机制的异步组件。取消令牌设置回调,以便在请求令牌信号取消时调用取消机制。

我可以在我的测试中调用此方法以在超时内执行其功能。

async Task TestInvoke()
{
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10))
{
try
{
await InvokeAsync(timeout.Token);
}
catch (TaskCancelledException ex)
{
if (ex.CancellationToken == timeout.Token)
{
throw new TimeoutException(
"Operation failed to complete in the allowed time.", ex);
}
throw;
}
}
}

我的期望是,在async方法中抛出OperationCanceledException将导致该方法返回的Task转换为"已取消"状态。然后,我希望任何等待此取消任务的尝试都应该抛出TaskCanceledException.

在我当前的场景中(代码与上面非常相似),当我等待任务时,我会得到一个OperationCanceledException。如果我检查任务的状态,我可以看到它处于"已取消"状态,并且没有与之关联的异常。

更奇怪的是,如果我在任务上调用Wait(),它会抛出一个包含预期TaskCanceledExceptionAggregateException

在什么情况下,等待取消的任务会抛出OperationCanceledException而不是更典型的TaskCanceledException

在什么情况下等待取消的任务会抛出OperationCanceledException而不是更典型的TaskCanceledException

这个问题太宽泛了。即使列举了今天发生这种情况的所有情况,明天也可能发生变化。

相反,我会这样说:

  • TaskCanceledException不是"更典型"。它最初用于基于任务的动态并行性,与异步编程无关。
  • OperationCanceledExceptionTaskCanceledException的基类。在代码中,您永远不应该捕获TaskCanceledException(除非您正在执行基于任务的动态并行性并且需要访问TaskCanceledException.Task)。

只是抓住OperationCanceledException

最新更新