Polly "retry" 在第一次失败重试时抛出 TaskCanceledException

Polly "retry" throws TaskCanceledException on first failure retry attempt

我已经在它自己的“重试”HttpClient DelegateHandler 中实现了 Polly,在一个写入 .NET Standard 2.0 的 dll 中。我有 Polly v7.2.3 包。我的 HttpClient 是 运行 与 HttpClientFactory 分开的,因为在 dll 的短暂生命周期中只会存在一个实例。

我的问题是:当我的互联网工作时,代码执行得很好。但是,当我断开互联网连接时,它会在第一次重试时抛出 TaskCanceledException 并且不再重试。这是我的代码的相关部分...

在我输入的 HttpClient 的构造函数中:

this.Client = new System.Net.Http.HttpClient(
new ATCacheDelegatingHandler(
    new RetryPolicyDelegatingHandler(
        new HttpClientHandler()))));

在我的重试委托处理程序中:

this.RetryPolicy =
Policy.Handle<HttpRequestException>()
    .Or<TaskCanceledException>()
    .WaitAndRetryAsync(numRetries,
        retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt-1) * 15));

所以我在这里对 SO 进行了研究,发现了这个非常有前途的解释和解决方案,建议我对结果调用 Dispose

这是我使用该解决方案更新后的代码。对 WaitAndRetryAsync 的调用抱怨它无法解析 OnRetry 方法,因为它正在寻找 'Action<Exception, TimeSpan>'

private void WaitAndRetry(int numRetries)
{
    this.RetryPolicy =
        Policy.Handle<HttpRequestException>()
            .Or<TaskCanceledException>()
            .WaitAndRetryAsync(numRetries,
                retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt-1) * 15)
                , OnRetry); // reference to the method below
}

// unable to match to these parameters from the "WaitAndRetryAsync" call above
private Task OnRetry(DelegateResult<HttpResponseMessage> response, TimeSpan span, int retryCount, Context context)
{
    if (response == null)
        return Task.CompletedTask;

    // this is the "Dispose" call from that SO solution I referenced above
    response.Result?.Dispose();
    return Task.CompletedTask;
}

遗憾的是,我使用的 Polly 版本不支持 DelegateResult<HttpResponseMessage> 参数。所有 onRetry 支持都希望第一个参数是“异常”。如果我无法使用一次性物品,我会使用 Dispose 解决方案在水中死去。

更新: 我希望能够调用 Dispose() 来影响来自其他 Whosebug 反馈的修复。但我不能,因为 onRetry 方法不支持同一组参数(即“响应”对象)。看起来 Polly API 已经改变了。如果是这样,获得响应的新方法是什么,这样我就可以 Dispose 了?或者有其他方法可以解决我遇到的错误吗?

所以我一直在尝试让这个解决方案工作或寻找另一种方法来解决这个异常。我欢迎任何有关如何指定要处置的对象的反馈。也欢迎使用其他方法。

您只需在声明保单时将 HttpResponseMessage 指定为 return 类型。

IAsyncPolicy<HttpResponseMessage> retryPolicy = Policy<HttpResponseMessage>
    .Handle<HttpRequestException>()
    .Or<TaskCanceledException>()
    .WaitAndRetryAsync(numRetries,
    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1) * 15), 
        OnRetry);

因此,请使用 Policy<HttpResponseMessage>.Handle...

而不是 Policy.Handle...