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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:27:00