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

Polly同步超时策略问题:超时后重试实现及策略生效疑问

Polly超时与重试策略问题解答

一、乐观超时策略未生效的原因

Polly的Optimistic超时是协作式机制,它依赖执行逻辑主动响应CancellationToken来中断操作。你的代码中使用Thread.Sleep(5000),这个方法不支持取消——不管超时策略如何配置,它都会阻塞至5秒结束,超时策略根本无法触发,自然不会抛出TimeoutRejectedException。

要让乐观超时生效,必须将执行逻辑改为支持取消的形式,比如在同步代码中主动检查取消信号:

wrap.Execute((ct) =>
{
    "Enter executed logic".Dump();
    for (int i = 0; i < 5; i++)
    {
        ct.ThrowIfCancellationRequested(); // 主动检测超时取消信号
        Thread.Sleep(1000);
    }
    "Exit executed logic".Dump();
});

二、悲观策略下执行逻辑进入两次的原因

你当前的策略包裹顺序是Policy.Wrap(retry, timeout),即重试策略在外层,超时策略在内层。这个顺序的执行流程是:

  1. 第一次执行:内层超时策略触发,抛出TimeoutRejectedException
  2. 外层重试策略捕获异常,触发重试(你设置了Retry(1),即最多重试1次)
  3. 第二次执行:再次触发超时,重试次数耗尽,最终抛出异常

因此执行逻辑会被执行两次。

三、实现“超时后暂停并重试直至达到最大次数”的方案

要实现超时后暂停再重试,需做以下调整:

1. 保留合理的策略包裹顺序

保持重试策略在外,超时策略在内的顺序,确保每次执行逻辑都应用超时规则,超时后触发重试。

2. 用WaitAndRetry替代Retry

Retry是立即重试,WaitAndRetry可指定重试前的等待时间,比如每次超时后暂停2秒再重试:

var retry = Policy
    .Handle<TimeoutRejectedException>() // 仅捕获超时异常,避免无差别重试
    .WaitAndRetry(2, retryAttempt => TimeSpan.FromSeconds(2), (ex, ts) =>
    {
        $"超时,将在{ts.TotalSeconds}秒后重试".Dump();
    });

3. 选择适配的超时策略

  • 悲观超时(Pessimistic):无需修改执行逻辑,Polly会在独立线程执行逻辑,超时后强制终止并抛出TimeoutRejectedException,重试策略捕获后触发等待重试。
  • 乐观超时(Optimistic):必须修改执行逻辑,让它支持CancellationToken,否则超时无法触发,重试也不会生效。

完整示例代码(悲观超时+等待重试)

var retry = Policy
    .Handle<TimeoutRejectedException>()
    .WaitAndRetry(2, retryAttempt => TimeSpan.FromSeconds(2), (ex, ts) =>
    {
        $"超时,将在{ts.TotalSeconds}秒后重试".Dump();
    });

var timeout = Policy
    .Timeout(1, Polly.Timeout.TimeoutStrategy.Pessimistic);

var wrap = Policy.Wrap(retry, timeout);

try
{
    wrap.Execute(() =>
    {
        "Enter executed logic".Dump();
        Thread.Sleep(5000);
        "Exit executed logic".Dump();
    });
}
catch (TimeoutRejectedException ex)
{
    $"最终超时:{ex.Message}".Dump();
}

是否必须让执行逻辑自身抛出超时?

  • 悲观超时:不需要。Polly通过线程调度强制终止执行逻辑,直接抛出TimeoutRejectedException。
  • 乐观超时:必须。因为乐观超时是协作式的,需要执行逻辑主动检查CancellationToken并抛出OperationCanceledException,Polly会将其包装为TimeoutRejectedException后抛出,才能被重试策略捕获。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:42:46