《ASP.NET Core技术内幕与项目实战》精简集-高级组件4.2:托管服务

本节内容,涉及到8.2(P265-P269),以WebApi说明为主。主要NuGet包:

 

一、一个简单的托管服务

//创建托管服务类
//TestBgService
public class TestBgService : BackgroundService
{
    private readonly ILogger<TestBgService> logger;
    public TestBgService(ILogger<TestBgService> logger)
    {
        this.logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await Task.Delay(5000);
        var str1 = await File.ReadAllTextAsync("d:/1.txt");
        for (int i = 0; i < 100; i++)
        {
            await Task.Delay(2000);
            logger.LogInformation(str1);
        }
    }
}

//在容器中注册托管服务
//Program.cs
builder.Services.AddHostedService<TestBgService>();

代码解读:

①托管类继承BackgroundService,BackgroundService实现了IHostedService,在IHostedService基础上增加了一些任务取消等逻辑

②托管类必须实现ExecuteAsync方法,方法体中是需要在后台执行的业务逻辑

③在Program入口类中,以依赖注入方式注册托管类服务,应用启动后,执行托管类的ExecuteAsync方法。方法在后台执行,不会阻塞AspNetCore的其它程序

④托管类中可以注入其它服务,但因为托管服务以单例方式注入,所以注入托管类的服务也必须是单例的。如果要在托管类中,注入短生命周期的服务,可以通过IServiceScope的方式

⑤托管类实现了IDisposable接口,但我们是以依赖注入方式使用,框架会帮我们自动处理

 

二、定时导出数据托管服务

 1 //创建ExportStringBgService托管类
 2 //ExportStringBgService.cs
 3 public class ExportStringBgService : BackgroundService
 4 {
 5     private readonly ILogger<ExportStringBgService> logger;
 6     private readonly IServiceScope serviceScope;
 7     public ExportStringBgService(IServiceScopeFactory scopeFactory)
 8     {
 9         serviceScope = scopeFactory.CreateScope();
10         var sp = serviceScope.ServiceProvider;
11         this.logger = sp.GetRequiredService<ILogger<ExportStringBgService>>();
12     }
13 
14     protected override async Task ExecuteAsync(CancellationToken stoppingToken)
15     {
16         while (!stoppingToken.IsCancellationRequested)
17         {
18             try
19             {
20                 StringBuilder sb = new StringBuilder();
21                 for (int i = 0; i < 100; i++)
22                 {
23                     sb.AppendLine($"abcdefg+{i}");
24                 }
25                 await File.WriteAllTextAsync("d:/1.txt", sb.ToString());
26                 logger.LogInformation("写入成功");
27 
28                 await Task.Delay(1000);
29             }
30             catch (Exception ex)
31             {
32                 logger.LogError(ex, "写入字符失败");
33                 await Task.Delay(1000);
34             }
35         }
36     }
37 
38     public override void Dispose()
39     {
40         base.Dispose();
41         serviceScope.Dispose();
42     }
43 }
44 
45 
46 //注册托管服务
47 //Program.cs
48 var builder = WebApplication.CreateBuilder(args);
49 builder.Services.AddHostedService<ExportStringBgService>();

代码解读:

5-12行:构造函数中注入①IServiceScopeFactory服务,通过它创建一个②范围服务serviceScope,在范围服务类,创建一个scope范围的③服务定位器ServiceProvide,通过服务定位器,注入生命周期为scope范围的服务ILogger。通过这种方式,可以在托管类中注入比单例生命周期更短的服务,比如DbContext。

38-41行:由于范围服务是我们在托管的单例生命周期中开的小窗,且serviceScope实现了IDisposable接口,需要手工Discope。

16,28行:通过while循环,持续执行后台服务。通过Task.Delay(1000),每秒钟定时执行一次。

18-34行:通过try...catch,当发生异常时,不会因为托管服务的未处理异常导致程序退出。

 

特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍

 

posted @ 2022-11-02 22:22  functionMC  阅读(314)  评论(0编辑  收藏  举报