C# IHostedService的用法 - 在ASP.NET Core中运行后台任务

来源:这里教程网 时间:2026-02-21 17:32:34 作者:

在 ASP.NET Core 中,如果需要运行长时间运行的后台任务,比如定时处理数据、轮询数据库、发送邮件或维护缓存,IHostedService 是一个非常合适的选择。它允许你在应用启动和关闭时执行自定义逻辑,非常适合托管后台服务。

什么是 IHostedService?

IHostedService 是一个接口,包含两个方法:

StartAsync(CancellationToken cancellationToken):在应用启动后调用,用于开始后台任务。 StopAsync(CancellationToken cancellationToken):在应用关闭时调用,用于优雅地停止任务。

你只需实现这个接口,将你的后台逻辑放入其中,ASP.NET Core 会自动管理它的生命周期。

如何使用 IHostedService?

以一个简单的定时任务为例,每 10 秒打印一条日志。

    创建一个类实现 IHostedService
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
public class TimedHostedService : IHostedService
{
    private readonly ILogger<TimedHostedService> _logger;
    private Timer? _timer;
    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
    }
    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Hosted Service is starting.");
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
        return Task.CompletedTask;
    }
    private void DoWork(object? state)
    {
        if (!_timer!.Disposed)
        {
            _logger.LogInformation("Timed Hosted Service is working. Time: {Time}", DateTime.Now);
        }
    }
    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }
}
    Program.cs 中注册服务:
var builder = WebApplication.CreateBuilder(args);
// 添加 Hosted Service
builder.Services.AddHostedService<TimedHostedService>();
var app = builder.Build();
app.Run();

这样,当应用启动时,StartAsync 被调用,定时器开始工作;关闭时,StopAsync 确保定时器被正确释放。

更复杂的场景:使用 BackgroundService

直接实现 IHostedService 对于复杂任务可能不够方便。ASP.NET Core 提供了抽象类 BackgroundService,更适合长时间运行的任务,比如从队列中消费消息。

using Microsoft.Extensions.Hosting;
using System.Threading.Channels;
public class QueuedHostedService : BackgroundService
{
    private readonly ChannelReader<string> _reader;
    public QueuedHostedService(Channel<string> channel)
    {
        _reader = channel.Reader;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await foreach (var message in _reader.ReadAllAsync(stoppingToken))
        {
            Console.WriteLine($"Processing message: {message}");
            await Task.Delay(1000, stoppingToken); // 模拟处理耗时
        }
    }
}

BackgroundService 内部实现了 IHostedService,并提供了一个抽象的 ExecuteAsync 方法,你可以在这里写主循环逻辑,避免手动管理 CancellationToken 和循环。

注册和依赖注入

所有实现 IHostedService 或继承 BackgroundService 的类都会被当作单例处理。它们可以在构造函数中注入任何已注册的服务,如 ILoggerDbContext 或自定义服务。

确保在 builder.Services 中使用 AddHostedService() 注册,而不是普通的 AddSingleton,这样才能由主机正确管理生命周期。

基本上就这些。用好 IHostedService,可以让后台任务与应用共存亡,既可靠又易于维护。

相关推荐

热文推荐