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

.NET 5 Worker服务如何检测系统关机事件

.NET 5 Worker 服务实现系统关机前自定义逻辑的方案

.NET 5及后续版本的Worker服务,默认通过Microsoft.Extensions.Hosting.WindowsServices包提供Windows服务承载能力,没有直接暴露和.NET Framework Windows服务完全同名的OnShutdown()重写入口,可通过以下两种方案实现完全同等的关机前自定义逻辑执行能力:

方案1:监听主机生命周期停止令牌(推荐)

  • 前置依赖:确保项目已安装Microsoft.Extensions.Hosting.WindowsServicesNuGet包,且主机构建阶段已调用UseWindowsService()开启Windows服务承载支持。
  • 触发逻辑:Windows向服务发送关机通知时,主机注入的停止令牌会自动标记为取消状态,此时执行的代码块和传统.NET Framework服务OnShutdown()的触发时机完全一致。
  • 配置优化:可通过Windows服务配置项自定义关机等待超时,避免自定义逻辑未执行完就被系统强制终止。

Program.cs 基础配置示例:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder(args)
    .UseWindowsService(options =>
    {
        options.CanShutdown = true; // 显式开启系统关机事件接收,默认值即为true
        options.ShutdownTimeout = TimeSpan.FromSeconds(30); // 给自定义清理逻辑预留30秒执行时间,可按需调整
    })
    .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
    })
    .Build();

await host.RunAsync();

Worker服务中实现关机逻辑示例:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // 服务正常运行时的常驻业务逻辑
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker运行中: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }

        // 代码执行到此处即代表收到系统关机/服务停止信号,对应传统OnShutdown触发时机
        _logger.LogInformation("收到关机信号,开始执行自定义清理逻辑");
        // 此处放置原OnShutdown()方法内的所有自定义逻辑
        await ExecuteCustomShutdownLogic();
    }

    private async Task ExecuteCustomShutdownLogic()
    {
        // 实现资源释放、数据持久化、状态上报等自定义需求
        await Task.CompletedTask;
    }
}

注意:不要把关机清理逻辑写在类的Dispose重写方法中,该阶段主机已开始回收核心服务依赖,极易出现依赖对象已释放导致的空引用、调用失败问题。

方案2:自定义服务生命周期类重写OnShutdown(对齐.NET Framework开发习惯)

如果需要完全复刻传统.NET Framework服务重写OnShutdown()的开发体验,可以自定义继承WindowsServiceLifetime类,直接重写对应方法,替换默认的服务生命周期实现即可。

自定义生命周期类示例:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.WindowsServices;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

public class CustomWindowsServiceLifetime : WindowsServiceLifetime
{
    private readonly ILogger<CustomWindowsServiceLifetime> _logger;

    public CustomWindowsServiceLifetime(
        IHostApplicationLifetime applicationLifetime,
        ILogger<CustomWindowsServiceLifetime> logger,
        IOptions<HostOptions> hostOptions)
        : base(applicationLifetime, logger, hostOptions)
    {
        _logger = logger;
    }

    protected override void OnShutdown()
    {
        _logger.LogInformation("触发系统关机事件,执行OnShutdown自定义逻辑");
        // 此处直接放置原.NET Framework服务中OnShutdown()内的业务逻辑
        RunCustomShutdownTasks();
        base.OnShutdown();
    }

    private void RunCustomShutdownTasks()
    {
        // 自定义关机逻辑实现
    }
}

在服务配置阶段替换默认生命周期实现:

.ConfigureServices(services =>
{
    services.AddSingleton<IHostLifetime, CustomWindowsServiceLifetime>();
    services.AddHostedService<Worker>();
})

注意:Windows系统默认给服务预留的关机执行时间存在全局上限,不要在关机逻辑中写入长时间阻塞的操作。如果确实需要更长的执行窗口,需要同步修改系统对应注册表的服务关机等待时长配置,否则逻辑会被系统强制中断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 13:01:20