托管服务

1、让代码运行在后台。比如服务器启动的时候在后台预先加载数据到缓存,每天凌晨三点把数据导出到备份数据库,每五秒在两张表之间同步一次数据。
2、托管服务实现IHostedService接口,一般编写从BackgroundService继承的类。
3、services.AddHostedService<DemoBgService>

1
2
3
4
5
6
7
8
public class HostedService1 : BackgroundService {
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
//在这里面执行后台代码
Console.WriteLine("后台启动");
await Task.Delay(3000);
Console.WriteLine("后台代码执行完成");
}
}
1
2
//Program.cs
builder.Services.AddHostedService<HostedService1>();

如果文件中发生异常:
1、程序会自动停止或退出。可以把HostOptions.BackgroundServiceExceptionBehavior设置为Ignore,程序会忽略异常,而不是停止程序,不过不推荐采用默认的设置。
2、起码应该用try…catch…包裹一下。
使用DI:
1、托管服务是以单例的生命周期注册到依赖注入容器中,因此不能注入生命周期为范围或者瞬态的服务,比如注入EFCore上下文的话,程序就会抛异常。
2、可以通过构造方法中注入一个IServiceScopeFactory,它可以用来创建一个IServiceScope对象,这样我们就可以通过IServiceScope来创建短生命周期的服务了。记得在Dispose中释放IServiceScope

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//HostedService
public class HostedService1 : BackgroundService {
private readonly IServiceScope serviceScope;
public HostedService1(IServiceScopeFactory factory) {
this.serviceScope = factory.CreateScope();
}
public override void Dispose() {
this.serviceScope.Dispose();
base.Dispose();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
var scopeTest = serviceScope.ServiceProvider.GetRequiredService<ScopeTest>();
scopeTest.Say();
}
}
1
2
3
//Progrom.cs
builder.Services.AddScoped<ScopeTest>();
builder.Services.AddHostedService<HostedService1>();