您现在的位置是:首页 >技术杂谈 >.Net托管服务网站首页技术杂谈
.Net托管服务
描述及使用场景
1、场景,代码运行在后台。比如服务器启动的时候在后台预先加载数据到缓存,每天凌晨3点把数据导出到备份数据库,每隔5秒钟在两张表之间同步一次数据。
2、托管服务实现IHostedService接口,一般编写从BackgroundService继承的类。
测试:延迟若干秒再读取文件,再延迟,再输出。
使用方式
创建需要使用托管代码的类并继承BackgroundService
public class HostedTest : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Delay(5000); string s = await File.ReadAllTextAsync(@"D:NoteJQuery1-jQuery入门.md"); await Task.Delay(20000); Console.WriteLine(s); } } |
在Program文件注册托管代码
builder.Services.AddHostedService<HostedTest>(); |
托管服务是以单例的生命周期注册到依赖注入容器中的。因此不能注入生命周期为范围或者瞬态的服务。
比如注入EF Core的上下文的话,程序就会抛出异常。
可以通过构造方法注入一个IServiceScopeFactory服务,它可以用来创建一个IServiceScope对象,这样我们就可以通过IServiceScope来创建短生命周期的服务了。记得在Dispose中释放IServiceScope。
public class HostedTest : BackgroundService { private readonly IServiceScope _service; private readonly ILogger<HostedTest> logger;
public HostedTest(IServiceScopeFactory service) { _service = service.CreateScope(); var sp = _service.ServiceProvider; this.logger = sp.GetRequiredService<ILogger<HostedTest>>(); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Delay(5000); string s = await File.ReadAllTextAsync(@"D:NoteJQuery1-jQuery入门.md"); await Task.Delay(1000); Console.WriteLine(s); logger.LogInformation(s); } public override void Dispose() { base.Dispose(); _service.Dispose(); } } |
托管服务的异常问题
1、从.NET 6开始,当托管服务中发生未处理异常的时候,程序就会自动停止并退出。可以把HostOptions.BackgroundServiceExceptionBehavior设置为Ignore,程序会忽略异常,而不是停止程序。不过推荐采用默认的设置,因为“异常应该被妥善的处理,而不是被忽略”。
2、要在ExecuteAsync方法中把代码用try……catch包裹起来,当发生异常的时候,记录日志中或发警报等。
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { try { await Task.Delay(5000); string s = await File.ReadAllTextAsync(@"D:NoteJQuery1-jQuery入门.md"); await Task.Delay(1000); Console.WriteLine(s); logger.LogInformation(s); } catch (Exception ex) { logger.LogError("异常处理:"+ex.Message); } } |