是否检测到C#中下游链接令牌的取消?

时间:2018-09-06 20:40:18

标签: c# cancellationtokensource

在OperationCancelledException的情况下,我正在尝试确保可取消代码的这些语义:

  1. 如果呼叫者是原因,请尊重并重新抛出

  2. 如果是我们或任何下游代码的原因,请将其翻译为 “不可用”响应

不幸的是,第二部分有问题。

如果下游代码链接了一个源,然后取消了+抛出,我似乎无法检测到它。我希望自己的消息源会引发IsCancellationRequested,但不会。

下面是一些说明问题的代码

    public void TestDownstreamCancellation()
    {
        var cancellationToken = new CancellationTokenSource().Token;
        var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
        try
        {
            var inner = CancellationTokenSource.CreateLinkedTokenSource(cts.Token);
            inner.Cancel();
            inner.Token.ThrowIfCancellationRequested();
        }
        catch (OperationCanceledException e)
        {
            // All right - we may be seeing this because we have cancelled the internal tasks (they execute
            // cancellationToken.ThrowIfCancellationRequested(), which is a rational way to bail out).
            // But it could also be because the outer (caller owned) token cancelled, in which case we should re-throw.
            if (e.CancellationToken == cancellationToken)
            {
                // The cause of the exception is that the caller of the composite requested termination, re-throwing!
                // Case is separated out for clatiry and (possibly) logging purposes.
                throw;
            }
            else if (cts.Token.IsCancellationRequested)
            {
                // Check if the cause is actually the passed-in token. If so, we should not translate this exception to a
                // ServiceUnavailable response. May be redundant, as the previous if branch should have caught this
                cancellationToken.ThrowIfCancellationRequested();

                // The cause of the exception is that one of the sub-tasks responded to a cancellation request by throwing
                // OperationCanceled. We translate this to ServiceUnavailable. It's always iffy to rely on exception behavior for control
                // flow, but in this case it's quite well-defined what's going on, as it's very common for an async task to honor a
                // cancellation request by throwing this exception.

                // return ServiceUnavailable;
            }
            else
            {
                // Something else threw, so raise it again and let the caller deal with it.
                throw;
            }
        }

我希望第二。分支被触发,但不会触发-相反,我们点击了第三个分支并重新抛出。

0 个答案:

没有答案