在什么情况下等待取消任务会抛出TaskCanceledException?

Pau*_*ner 4 c# async-await

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

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

该方法调用一个异步组件,该组件公开某种取消机制.当请求令牌信号取消时,取消令牌设置回调以调用取消机制.

我可以在测试中调用此方法在超时内运行其功能.

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的期望是OperationCanceledExceptionasync方法内抛出会导致方法Task返回到"已取消"状态.然后我期待任何等待这个被取消的任务的尝试应该抛出一个TaskCanceledException.

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

更奇怪的是,如果我调用Wait()该任务,它会抛出AggregateException包含预期的任务TaskCanceledException.

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

Ste*_*ary 6

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

这个问题太宽泛了.即使列举了今天发生的所有场景,它也可能在明天发生变化.

相反,我会这样说:

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

只是抓住了OperationCanceledException.