使用DI与Hosted Service的控制台应用执行后无法退出该如何解决
问题根因
直接手动调用IHostedService的StopAsync方法仅会执行当前服务的停止逻辑,并不会通知通用主机(IHost)触发全局关闭流程,因此Host.Run()会持续等待关闭信号,进程无法正常退出。
推荐解决方案:使用IHostApplicationLifetime触发优雅关闭
这是.NET官方提供的标准方案,会触发所有注册服务的停止逻辑、资源释放流程,完成后自动退出进程,无资源泄漏风险。
步骤1:注入IHostApplicationLifetime到MainService
修改MainService的构造函数,注入IHostApplicationLifetime实例并保存为私有字段:
public class MainService: IHostedService { private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly IHostApplicationLifetime _appLifetime; public MainService(Service1 service1, Service2 service2, Service3 service3, IServiceProvider services, IConfiguration config, IHostApplicationLifetime appLifetime) { _appLifetime = appLifetime; // 其余原有初始化逻辑 }
步骤2:业务逻辑完成后调用StopApplication
注意不要在StartAsync中直接阻塞执行数小时的任务,否则会卡住主机的启动流程,建议将业务逻辑放到后台线程执行,执行完成后调用_appLifetime.StopApplication()触发全局关闭:
public Task StartAsync(CancellationToken cancellationToken) { // 后台执行长时间任务,不阻塞主机启动 _ = Task.Run(async () => { try { // 此处替换为你的实际业务逻辑,支持异步 await DoYourLongTimeTaskAsync(cancellationToken); _logger.Info("任务执行完成,准备退出程序"); } catch (Exception ex) { _logger.Error(ex, "任务执行过程中出现异常"); } finally { // 触发全局优雅关闭,主机将自动调用所有IHostedService的StopAsync,完成后退出进程 _appLifetime.StopApplication(); } }, cancellationToken); return Task.CompletedTask; }
修改后不需要调整Program.cs的代码,主机收到关闭信号后会自动完成清理,Host.Run()方法执行完成后程序正常退出。
兜底方案:强制退出进程
如果遇到特殊场景无法走优雅关闭流程,可以调用Environment.Exit(0)直接终止进程,注意该方法不会执行任何未完成的清理逻辑(如未提交的事务、未释放的资源),仅作为兜底方案使用:
// 任务完成后直接调用即可 Environment.Exit(0);
内容的提问来源于stack exchange,提问作者lenny
相关产品推荐
相关产品推荐

