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

Posted

技术标签:

【中文标题】什么情况下等待取消的任务会抛出TaskCanceledException?【英文标题】:Under what circumstances will awaiting a cancelled task throw TaskCanceledException? 【发布时间】:2017-03-21 14:01:14 【问题描述】:

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

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

【问题讨论】:

***.com/questions/26577519/… 这应该对你有帮助。 【参考方案1】:

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

这个问题太笼统了。即使人们列举了今天发生这种情况的所有场景,它也可能在明天发生变化。

相反,我会这样说:

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

只需抓住OperationCanceledException

【讨论】:

TaskCanceledException 由已取消的任务生成,在调用 Wait() 时不会抛出其他异常,并且是由 TaskCompletionSource 提供的异常;无论起源如何,它都与基于任务的异步编程密切相关。

以上是关于什么情况下等待取消的任务会抛出TaskCanceledException?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在这种情况下编译器会抛出“未定义的引用...”错误?

Task.WaitAll在一个任务抛出时挂起,另一个任务与第一个任务同步

HttpClient - 任务被取消?

在没有ToList()的情况下运行时,在Linq的SelectMany()中读取文件会抛出System.IO.IOException

jdk7 watch service API中,啥时候会抛出OVERFLOW事件?

为什么调试器会抛出“读取访问冲突。这是nullptr”例外吗?