Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Associate a CancellationToken with an async method's Task

Question: Is there a way to associate a CancellationToken with the Task returned from an async method?

Generally, a Task will end up in the Canceled state if an OperationCancelledException is thrown with a CancellationToken matching the Task's CancellationToken. If they don't match, then the task goes into the Faulted state:

void WrongCancellationTokenCausesFault()
{
    var cts1 = new CancellationTokenSource();
    var cts2 = new CancellationTokenSource();
    cts2.Cancel();

    // This task will end up in the Faulted state due to the task's CancellationToken
    // not matching the thrown OperationCanceledException's token.
    var task = Task.Run(() => cts2.Token.ThrowIfCancellationRequested(), cts1.Token);  
}

With async/await, I haven't found a way to set the method's Task's CancellationToken (and thus achieve the same sort of functionality). From my testing, it seems that any OperationCancelledException will cause the async method to enter the Cancelled state:

async Task AsyncMethodWithCancellation(CancellationToken ct)
{
    // If ct is cancelled, this will cause the returned Task to be in the Cancelled state
    ct.ThrowIfCancellationRequested(); 
    await Task.Delay(1);

    // This will cause the returned Task to be in the Cancelled state
    var newCts = new CancellationTokenSource();
    newCts.Cancel();
    newCts.Token.ThrowIfCancellationRequested();
}

It would be nice to have a little more control, since if a method I call from my async method is cancelled (and I don't expect cancellation--i.e. its not this Task's CancellationToken), I would expect the task to enter the Faulted state--not the Canceled state.

like image 888
Matt Smith Avatar asked Oct 19 '25 00:10

Matt Smith


1 Answers

I think the design works well for the common case: if any child operations are cancelled, then the cancellation propagates to the parent (the most common case is that the parent and child share cancellation tokens).

If you want different semantics, you can catch the OperationCanceledException in your async method and throw an exception that fits the semantics you need. If you want to use these semantics repeatedly, an extension method for Task should fit the bill.

like image 150
Stephen Cleary Avatar answered Oct 21 '25 14:10

Stephen Cleary



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!