c# - 如何使用 ContinueWith 处理任务取消?

标签 c# .net asynchronous task-parallel-library cancellationtokensource

我有以下示例:

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 获得了一个取消 token 。为此,我使用 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 正确处理取消吗?

最佳答案

ContinueWith 的注释具体说明:

If the continuation criteria specified through the continuationOptions parameter are not met, the continuation task will be canceled instead of scheduled.

由于未满足您为前提指定的条件(即未取消),因此将继续设置为取消。您等待取消的任务,因此导致 DoAsync 出现操作取消异常错误。

关于c# - 如何使用 ContinueWith 处理任务取消?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46055011/

相关文章:

c# - 带有关闭按钮的气球工具提示 - C#

c# - 为什么我的 ConcurentSet 不起作用?

c# - 在编译代码或外部文件中嵌入大量常量

asynchronous - Meteor 包裹异步

c# - C# 的多线程和并发

asynchronous - Kotlin中的异步预定作业

c# - 如何在 C# 中实现类之间的共享行为(当然没有多重继承)

c# - Visual Studio 2008 表单设计器弄乱了 bool 属性值

c# - 绑定(bind)重定向不重定向?

c# - 单击 RadioButton 时,我想在 View 中显示模型中的值