托管服务
大约 1 分钟
托管服务
使用场景
- 服务器启动的时候在后台预先加载数据到缓存
- 每天固定时间把数据导出到备份数据库
实现
- 托管服务需要实现
IHostedService
接口,一般编写从BackgroundService
继承的类 - 添加到服务:
services.AddHostedService<DemoBgService>();
异常处理
- 从.NET 6开始,当托管服务中发生未处理异常的时候,程序就会自动停止并退出。
HostOptions.BackgroundServiceExceptionBehavior
设置为 Ignore,程序会忽略异常ExecuteAsync
方法应该对异常进行处理或预警
依赖注入
- 托管服务是以单例的生命周期注册到依赖注入容器中的。
- 因此不能在托管服务中注入生命周期为范围或者瞬态的服务。
- 如何使用短生命周期服务:
- 可以通过构造方法注入一个
IServiceScopeFactory
服务 - 利用
IServiceScopeFactory
服务创建IServiceScope
对象 - 在
IServiceScope
对象中创建短生命周期的服务 - 在
Dispose
中释放IServiceScope
- 可以通过构造方法注入一个
案例:定时任务
public class MyBackgroundService : BackgroundService
{
private readonly IServiceScopeFactory serviceScopeFactory;
public MyBackgroundService(IServiceScopeFactory serviceScopeFactory)
{
this.serviceScopeFactory = serviceScopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using var serviceScope = serviceScopeFactory.CreateScope();
EntityDbContext? context = serviceScope.ServiceProvider.GetService<EntityDbContext>();
ILogger? logger = serviceScope.ServiceProvider.GetService<ILogger>();
try
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine($"{DateTime.Now.ToShortTimeString()}: Total books {await context.Books.CountAsync()}");
await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken);
}
}
catch (Exception ex)
{
logger.LogError(ex.Message, ex);
}
}
}