C# 在什么情况下,等待已取消的任务会引发TaskCanceledException?

C# 在什么情况下,等待已取消的任务会引发TaskCanceledException?,c#,async-await,C#,Async Await,我习惯于在处理异步操作的取消时能够执行异步模式: public async Task InvokeAsync(CancellationToken cancellationToken) { using(cancellationToken.Register(handler.Stop)) { try { await handler.HandleAsync(); } catch(HandlerStop

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

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
将导致该方法返回的
任务转换为“已取消”状态。然后,我希望任何等待此已取消任务的尝试都会引发
TaskCanceledException

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


更奇怪的是,如果我对任务调用
Wait()
,它会抛出一个
aggregateeexception
,其中包含预期的
TaskCanceledException


在什么情况下,等待取消的任务会抛出
操作取消异常
,而不是更典型的
任务取消异常


在什么情况下,等待取消的任务会抛出
操作取消异常
,而不是更典型的
任务取消异常

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

相反,我要说:


  • TaskCanceledException
    不是“更典型的”。它最初用于基于任务的动态并行,与异步编程无关

  • OperationCanceledException
    TaskCanceledException
    的基类。在代码中,永远不要捕获
    TaskCanceledException
    (除非您正在执行基于任务的动态并行并且需要访问
    TaskCanceledException.task

只需捕获
OperationCanceledException

这应该会对您有所帮助。
TaskCanceledException
由已取消的任务生成,在调用
Wait()
时不会引发其他异常,并且是由
TaskCompletionSource
提供的异常;无论其来源如何,它都与基于任务的异步编程密切相关。