BackgroundService 是 ASP.NET Core 中实现长运行托管后台任务的标准方式,需继承并重写 ExecuteAsync,使用 CancellationToken 响应关闭,通过 AddHostedService 注册,支持 DI 但需注意作用域生命周期。
在 C#(特别是 .NET 5+ 的 ASP.NET Core 应用中),BackgroundService 是实现**长运行、托管后台任务**的标准方式。它由 IServiceCollection 托管,随应用启动/停止自动生命周期管理,比裸写线程或 Task.Run 更安全、更可控。
核心是继承 BackgroundService,并重写 ExecuteAsync(CancellationToken stoppingToken) 方法。该方法会被框架调用一次,你需在此内部实现持续运行的逻辑(通常用循环 + 延迟)。
stoppingToken 检查取消请求,确保能响应应用关闭while(true) 死循环,要用 await Task.Delay(..., stoppingToken) 支持中断示例:每 5 秒打印一次时间
public class ClockService : BackgroundService
{
private readonly ILogger _logger;
public ClockService(ILogger logger) => _logger = logger;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("当前时间: {Time}", DateTime.Now);
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
}
}
.NET 6+ 推荐在 Program.cs 的服务容器中注册,使用 AddHostedService 或 AddScoped(推荐前者)。
StartAsync,关闭时调用 StopAsync
注册代码(Program.cs):
var builder = WebApplication.CreateBuilder(args); // 注册后台服务(自动托管) builder.Services.AddHostedService(); // 其他服务... builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); app.Run();
BackgroundService 支持构造函数注入,可安全使用 ILogger、IConfiguration、数据库上下文(注意:若用 EF Core,请用 IServiceScopeFactory 创建作用域,避免跨作用域共享 DbContext)。
IServiceScopeFactory 创建临时 scope带数据库操作的片段示例:
public class DataSyncService : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger _logger;
public DataSyncService(IServiceScopeFactory scopeFactory, ILogger logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope = _scopeFactory.CreateScope();
var context = scope.ServiceProvider.GetRequiredService();
// 执行查询或保存...
var count = await context.Users.CountAsync(stoppingToken);
_logger.LogInformation("用户总数: {Count}", count);
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}
BackgroundService 的 StartAsync 和 StopAsync 是可重写的,但多数场景无需干预。需注意:
StopAsync 有默认 5 秒超时(可通过 IHostOptions.ShutdownTimeout 修改)stoppingToken 触发后尽快退出循环,并在 StopAsync 中做收尾(如释放资源、提交事务)StopAsync 中执行阻塞 IO 或长时间等待 —— 应配合 stoppingToken 提前退出基本上就这些。用好 BackgroundService 关键就三点:正确响应取消令牌、合理使用 DI、避免在后台任务里滥用生命周期不匹配的服务。它不是万能定时器(复杂调度建议用 Quartz.NET 或 Hangfire),但对轻量级周期性任务非常够用。