You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Polly异步重试策略时重试前记录日志的正确方法

问题根因

WaitAndRetryAsync的onRetryAsync参数要求绑定的委托必须返回Task类型,你当前传入的lambda直接调用返回值为void的同步LogInfo方法,返回值不匹配委托签名,因此触发编译错误。另外原代码日志中引用的result.Result变量不在当前委托的参数列表中,属于隐藏的运行时错误。

正确实现方式

根据你使用的日志方法是同步还是异步,选对应写法即可:

场景1:使用同步日志方法(返回void)

直接在lambda中显式返回Task.CompletedTask即可匹配委托签名,不需要额外加async包装产生多余的性能开销:

var policy = Polly.Policy
    .Handle<SomeExceptionType>()
    .WaitAndRetryAsync(
        retryCount: this.maxRetryCount,
        sleepDurationProvider: (_, e, context) =>
        {
            var waitTimeSpan = TimeSpan.FromSeconds(1);
            if (e != null && e is SomeExceptionType someException)
            {
                var retryAfterFromException = someException.Headers?.RetryAfter.Delta;
                if (retryAfterFromException > TimeSpan.Zero)
                {
                    waitTimeSpan = retryAfterFromException.GetValueOrDefault();
                }
            }
            return waitTimeSpan;
        },
        onRetryAsync: (e, timeSpan, retryCount) => 
        {
            // 修正原代码不存在的result变量,从异常对象取状态码
            this.logger.LogInfo($"Request failed with {e.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}");
            return Task.CompletedTask;
        });

如果习惯用async语法,也可以写成async lambda,效果一致:

onRetryAsync: async (e, timeSpan, retryCount) => 
{
    this.logger.LogInfo($"Request failed with {e.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}");
    await Task.CompletedTask;
}

场景2:使用异步日志方法(返回Task)

直接await异步日志方法即可,编译器会自动生成符合签名的Task返回值:

onRetryAsync: async (e, timeSpan, retryCount) => 
{
    await this.logger.LogInfoAsync($"Request failed with {e.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}");
}
注意事项
  • 禁止用async void写法编写onRetryAsync的委托,会丢失异步执行上下文,导致异常无法被Polly捕获,甚至触发进程级崩溃。
  • 若需要记录请求ID、业务标识等自定义上下文,可以使用带Context参数的onRetryAsync重载,执行Policy时传入对应上下文数据即可。
  • 仅当你通过HandleResult<T>匹配返回值触发重试时,onRetry委托才会传入result参数,仅捕获异常的重试场景下,所有错误信息都需要从异常对象中提取。

内容的提问来源于stack exchange,提问作者Satashree Roy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:39:04