简体   繁体   中英

Proper way to correlate an OperationCanceledException to a CancellationToken

I'm using an async api which supports cancellation and I'm passing to that api a CancellationToken instance. As usual, if the cancellation is requested on the passed token, the api that I'm invoking will throws an OperationCanceledException (this is the standard cooperative cancellation pattern of the .NET framework).

I want to be able to catch the OperationCanceledException if and only if it is the exception raised due to the cancellation of the provided cancellation token.

The following code illustrates what I'm trying to achieve:

try 
{
    await _service.DoSomethingAsync(cancellationToken: token);
}
catch (OperationCanceledException ex) when ( /* here I want a condition signifying that the OperationCanceledException is caused by the cancellation of the token object */)
{
    // avoid logging the exception: this is raised by design (cooperative cancellation)
    throw;
}
catch (Exception ex) 
{
    _logger.LogError(ex, "An error occurred: {0}", ex.Message);
    throw;
}

For the exception filter of the code above I have basically two ideas:

  • checking the IsCancellationRequested property on the token object: when (token.IsCancellationRequested)
  • checking the CancellationToken property on the ex object: when (ex.CancellationToken == token)

What is the right way to do the check I want to perform? Are the two ways showed above equivalent? Is there a best practice?

IMPORTANT NOTE : I know that the code showed above can be written in a more efficient way, because catching exceptions is an expensive operation. The best thing to do is probably removing the first catch block at all, and only catching an Exception if and only if it is not related with the cancellation of the token object. I'm aware of that, but that's not the point of my question. I have written the code in the question that way only for clarity , because the whole point of my question is how to properly correlate an OperationCanceledException with the CancellationToken which has caused the exception itself.

I want to be able to catch the OperationCanceledException if and only if it is the exception raised due to the cancellation of the provided cancellation token.

You can't do this exactly , but you can "catch the canceled exception only if my provided token has been cancelled", which is usually good enough.

when (token.IsCancellationRequested) is what you want.

Don't check the ex.CancellationToken , because the method you're calling may be observing a linked cancellation token, which would be different than the one you provided.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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