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

Polly .Net配合IHostApplicationLifetime实现应用优雅关停的异常问题

问题根因

  • IHostApplicationLifetime.Stop() 是异步触发应用关停流程的方法,调用后不会立即终止当前线程的执行逻辑,关停信号需要传递到各个执行链路才会生效
  • 你把关停逻辑放到了Polly的异常过滤器Handle<DatabaseException>(ex => ...)中,且方法返回了true,Polly会判定该异常需要执行重试策略,会直接进入重试等待流程,不会响应尚未完成的关停信号

修复方案

1. 不要在Polly的异常过滤器中编写业务逻辑

异常过滤器仅用来判断异常是否需要被策略处理,关停逻辑移到重试回调或单独的异常捕获分支,同时绑定应用关停的CancellationToken中断执行流:

private IHostApplicationLifetime _applicationLifetime;
// 取IHostApplicationLifetime自带的关停信号Token
private CancellationToken _stoppingToken => _applicationLifetime.ApplicationStopping;

public void CreatePolicy() 
{
    var policy = Policy
        // 过滤器仅做异常类型判断
        .Handle<DatabaseException>()
        .WaitAndRetryForever(
            retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
            (exception, timespan) => 
            {
                // 遇到DatabaseException直接触发关停
                if (exception is DatabaseException)
                {
                    _applicationLifetime.Stop();
                }
                HandleRetry(exception, timespan, _stoppingToken);
            })
        // 绑定关停token,token触发后会直接终止重试等待和策略执行
        .WithCancellation(_stoppingToken);
}

2. 主动中断当前执行流

如果需要完全避免后续任何逻辑执行,可在触发关停后主动抛出取消异常,直接终止当前执行链路:

public bool HandleDatabaseException(Exception ex) 
{
   _applicationLifetime.Stop();
   // 抛出取消异常,直接中断所有后续执行,不会再进入Polly重试逻辑
   throw new OperationCanceledException("数据库异常触发应用关停", ex, _stoppingToken);
}

3. 执行策略时传入关停token

所有通过该Polly策略执行业务代码的位置,都要传入应用关停的CancellationToken,确保正在运行的业务逻辑可以响应关停信号:

// 示例执行逻辑
policy.Execute(token => 
{
    // 你的数据库操作等业务逻辑
}, _stoppingToken);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 12:42:04