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

.NET 6中BackgroundService的停止方式有哪些?

BackgroundService的停止方式及场景分析

问题场景

我使用.NET 6开发了一个部署在Windows服务器上的REST API,通过继承BackgroundService实现了一个后台进程,仅自行实现了该类的ExecuteAsync方法,方法内包含一个使用cancellationToken的延迟循环。代码如下:

public async Task ExecuteAsync(CancellationToken cancellationToken)
{
    try
    {
        .....   
        foreach (var number in numbers)
        {
            ....
            await Task.Delay(100, cancellationToken);
            .....
        }
        .....
    }
    catch (Exception e)
    {
        ........ 
        _logger.LogError(e.GetBaseException(),"Failed processing requested numbers");
        throw;
    }
}

从日志捕获的异常可知,cancellationToken被触发取消进程,按官方文档这属于“优雅关闭”,但后续仍有大量请求日志显示应用还在运行。想了解BackgroundService除了优雅关闭外还有哪些停止方式。

核心说明

首先要明确:BackgroundService的ExecuteAsync方法触发取消,仅代表该后台服务实例停止,而非整个ASP.NET Core应用关闭。因为ASP.NET Core的主宿主(处理HTTP请求的核心进程)和后台服务是独立的宿主组件,后台服务停止不会主动终止主宿主。

BackgroundService的所有停止方式

1. 优雅关闭(默认触发方式)

  • 触发时机:当应用宿主收到系统停止信号时(比如Windows服务停止指令、控制台按Ctrl+C、云平台部署停止命令),会向所有IHostedService(包含BackgroundService)传递取消令牌。
  • 行为:ExecuteAsync中的cancellationToken被触发,Task.Delay会抛出TaskCanceledException;若该异常未被捕获(或捕获后重新抛出),后台服务会正常停止,但主宿主不会终止,应用仍可处理HTTP请求。

2. 未处理的非取消类异常终止

如果ExecuteAsync中抛出未被捕获的非取消类型异常(如业务异常、空引用异常等),且未在宿主配置中设置忽略该类异常,整个应用宿主会直接终止,同时停止所有服务。

  • 注意:你当前代码中捕获异常后重新抛出,若抛出的是TaskCanceledException,宿主不会终止;若为其他异常,宿主会停止。

3. 主动调用宿主停止方法

在应用内部,可通过依赖注入获取IHostApplicationLifetime,调用StopApplication()方法,直接触发整个宿主的停止流程,同时通知所有BackgroundService执行优雅关闭逻辑。
示例代码:

private readonly IHostApplicationLifetime _hostLifetime;

public YourBackgroundService(IHostApplicationLifetime hostLifetime)
{
    _hostLifetime = hostLifetime;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    // 满足特定条件时,主动终止整个应用
    if (someCriticalCondition)
    {
        _hostLifetime.StopApplication();
        return;
    }

    // 原有业务逻辑
    try
    {
        foreach (var number in numbers)
        {
            await Task.Delay(100, stoppingToken);
            // ...
        }
    }
    catch (Exception e)
    {
        _logger.LogError(e.GetBaseException(), "Failed processing requested numbers");
        // 若需要异常时终止应用,可在此调用StopApplication
        _hostLifetime.StopApplication();
    }
}

4. 系统层面强制终止

直接通过系统工具强制结束应用进程(比如Windows任务管理器结束进程、taskkill命令),这种方式不会触发BackgroundService的优雅关闭逻辑,属于暴力停止,可能导致数据未持久化、资源未释放等问题。

5. 宿主超时强制停止

在Program.cs中配置宿主的停止超时时间,若BackgroundService在超时时间内未完成优雅关闭,宿主会强制终止该后台服务实例(默认不终止整个应用,可通过配置调整):

builder.Host.ConfigureServices(services =>
{
    services.Configure<HostOptions>(options =>
    {
        // 设置30秒的停止超时
        options.ShutdownTimeout = TimeSpan.FromSeconds(30);
    });
});

针对你场景的建议

如果你希望后台服务停止时整个应用也随之关闭,可以在ExecuteAsync的异常处理逻辑中,判断异常类型(或业务条件),调用IHostApplicationLifetime.StopApplication()来终止整个宿主进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:12:39