【问题标题】:Polly "retry" throws TaskCanceledException on first failure retry attemptPolly“重试”在第一次失败重试尝试时抛出 TaskCanceledException
【发布时间】:2022-01-29 03:08:03
【问题描述】:

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

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

在我输入的 HttpClient 的 ctor 中:

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 进行了研究,发现了这个非常有希望的解释和解决方案,建议我在结果上调用 DisposeHttpClient Polly WaitAndRetry policy

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

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&lt;HttpResponseMessage&gt; 参数。所有onRetry 支持都要求第一个参数是“异常”。如果我无法访问一次性物品,我会使用Dispose 解决方案在水中死去。

更新:我希望能够调用 Dispose() 以影响其他 StackOverflow 反馈的修复。但我不能,因为onRetry 方法不支持同一组参数(即“响应”对象)。 Polly API 似乎发生了变化。如果是这样,访问响应的新方法是什么,以便我可以Dispose 呢?是这样还是有其他方法可以解决我遇到的错误?

因此,我一直在尝试使此解决方案正常工作或寻找另一种解决此异常的方法。我欢迎任何有关如何指定要处理的对象的反馈。也欢迎替代方法。

【问题讨论】:

  • 您的问题是什么?如何解决编译错误?
  • 确实有一个WaitAndRetryAsync 重载接受您的OnRetry 方法:Polly's source code
  • 对不起,如果我不清楚。我希望能够调用“Dispose()”来影响来自其他 StackOverflow 反馈的修复。但我不能,因为 OnRetry 方法不支持同一组参数(即“响应”对象)。 Polly API 似乎发生了变化。如果是这样,访问响应以便我可以处理它的新方法是什么?是这样还是有其他方法可以解决我遇到的错误?
  • 不,它没有改变。如果您查看源代码并启用责备,那么您可以看到在过去 6 年中过载没有更新。

标签: c# dotnet-httpclient polly retrypolicy delegatinghandler


【解决方案1】:

您只需在声明策略时将HttpResponseMessage 指定为返回类型。

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

所以,不要使用Policy.Handle...,而是使用Policy&lt;HttpResponseMessage&gt;.Handle...

【讨论】:

  • @JeffLehner 我已将问题中的代码复制粘贴到 .NET 5 控制台应用程序中,并修复了编译问题。您是否也更改了 this.RetryPolicy 的类型?在您的情况下,它是 IAsyncPolicy。
  • 我在这里做了类似的事情,构建问题就消失了。我需要等待 30 分钟才能测试它。谢谢你一直陪着我。我会告诉你进展如何。
  • 这解决了我的“构建”问题!谢谢你的帮助!另外,现在我看到了重试。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-14
  • 2018-11-21
  • 2022-11-17
  • 1970-01-01
相关资源
最近更新 更多