简体   繁体   English

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

[英]How to handle task cancellation using ContinueWith?

I've got the following example: 我有以下示例:

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");
}

I've created a method ( DoAsync ) that does some asynchronous work and can be cancelled at any time. 我创建了一个方法( DoAsync ),它可以执行一些异步工作,并且可以随时取消。

As you can see Task.Run gets a cancellation token. 如您所见,Task.Run获取取消令牌。 For this reason I created continuation task with continuationOptions = TaskContinuationOptions.OnlyOnCanceled . 出于这个原因,我使用continuationOptions = TaskContinuationOptions.OnlyOnCanceled创建了延续任务。

As a result I expected continuation task to be called only when cancellation is requested and in other cases - ignored. 因此,我预计只有在请求取消时才会调用继续任务,而在其他情况下会被忽略。

But in my implementation task returned by ContinueWith throws an exception when its antecedent task is not being cancelled: 但是在我的实现任务中, ContinueWith返回的任务在其前一个任务未被取消时抛出异常:

DoAsync started
DoAsync Run

Inside try-catch block
System.AggregateException...

A task was canceled.

I can fix this by adding another ContinueWith as in the example below: 我可以通过添加另一个ContinueWith来解决这个问题,如下例所示:

await Task.Run(() =>
        Console.WriteLine("DoAsync Run"),
        ctc.Token
    )
    .ContinueWith(antecedent =>
        Console.WriteLine("DoAsync Run cancelled"),
        TaskContinuationOptions.OnlyOnCanceled
    )
    .ContinueWith(antecedent => { });

And this code doesn't throw any exceptions. 并且此代码不会抛出任何异常。

But can I handle the cancellation using single ContinueWith properly? 但我可以使用单个ContinueWith正确处理取消吗?

The remarks for ContinueWith specifically state: ContinueWith的评论具体说明:

If the continuation criteria specified through the continuationOptions parameter are not met, the continuation task will be canceled instead of scheduled. 如果未满足通过continuationOptions参数指定的继续标准,则将取消继续任务而不是已安排。

Since the criteria you specified for the antecedent weren't met, (namely, it wasn't cancelled) the continuation was set to be cancelled. 由于您未满足为先行条件指定的标准(即,未取消),因此将取消延期。 You awaited the cancelled task, which therefore result in DoAsync faulting with an operation cancelled exception. 您等待已取消的任务,因此导致DoAsync出现操作取消异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM