当前位置: 首页 > article >正文

IHostedLifecycleService是如何管理后台任务的

在本文中,我们将介绍 IHostedLifecycleService接口,并通过几个用例来了解它是如何扩展 IHostedService接口并实现对托管服务生命周期更精细控制的。

一、什么是 IHostedService 接口

IHostedService接口是 .NET 中的一个强大功能,我们可以通过它管理应用程序中的后台任务,
它包含两个方法 StartAsyncStopAsync,其中 StartAsync方法用于实现启动后台任务的逻辑,当服务器启动并且 IHostApplicationLifetime.ApplicationStarted被触发时会调用这个方法。 当应用程序停止时会调用 StopAsync方法,我们使用它来停止后台任务并处理未托管的资源。

二、IHostedLifecycleService 接口

IHostedLifecycleService接口继承自 IHostedService接口,它对托管服务的启动和停止进行了更精细控制,引入了在服务启动或停止前后执行的新方法:StartingAsyncStartedAsyncStoppingAsyncStoppedAsync。下面我们来简单了解一下这四个方法的触发时机,首先,StartingAsync方法会在 StartAsync方法之前触发,而StartedAsync方法是在 StartAsync方法之后触发。同样,在 StoppingAsync方法之前会触发 StoppedAsync方法,在 StopAsync方法之后会触发 StoppedAsync方法。

下面,我们通过一个简单的例子来看一下在实际开发中的应用。
首先,我们定义了两个类 HostedService1 HostedService2,在这两个类中都实现了 IHostedLifecycleService接口:

public class HostedService1 (ILogger<HostedService1> logger) : IHostedLifecycleService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService1 )} start.");
        return Task.CompletedTask;
    }
    public Task StartedAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService1 )} started.");
        return Task.CompletedTask;
    }
    public Task StartingAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService1 )} starting.");
        return Task.CompletedTask;
    }
    public Task StopAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService1 )} stop.");
        return Task.CompletedTask;
    }
    public Task StoppedAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService1 )} stopped.");
        return Task.CompletedTask;
    }
    public Task StoppingAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService1 )} stopping.");
        return Task.CompletedTask;
    }
}

public class HostedService2(ILogger<HostedService2> logger) : IHostedLifecycleService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService2)} start.");
        return Task.CompletedTask;
    }
    public Task StartedAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService2)} started.");
        return Task.CompletedTask;
    }
    public Task StartingAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService2)} starting.");
        return Task.CompletedTask;
    }
    public Task StopAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService2)} stop.");
        return Task.CompletedTask;
    }
    public Task StoppedAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService2)} stopped.");
        return Task.CompletedTask;
    }
    public Task StoppingAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation($"Service {nameof(HostedService2)} stopping.");
        return Task.CompletedTask;
    }
}

在上面代码中,我们在每个方法里都打印了服务名和方法名,接着我们将这两个类注册为托管服务并运行应用程序:

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<HostedService1>();
builder.Services.AddHostedService<HostedService2>();
var app = builder.Build();
app.Run();

上面代码中,我们使用 AddHostedService<THostedService>方法在 DI 容器中注册托管服务。 运行程序,将看到如下输出:
在这里插入图片描述
在输出的信息中,我们可以看到方法的调用顺序与预期一致。

三、当前托管服务的启动和停止

在默认情况下,应用会按顺序执行托管服务的启动和停止, 也就是说HostedService2StartingAsync方法只在HostedService1的相同方法返回之后执行。但是,从 .NET 8 开始我们可以通过设置ServiceStartConcurrentlyServiceStopConcurrently来改变这种行为,代码如下:

builder.Services.Configure<HostOptions>(options =>
{
    options.ServicesStartConcurrently = true;
    options.ServicesStopConcurrently = true;
});

设置为 true 时,所有托管服务将同时启动和停止,但是在所有服务的当前生命周期返回之前,任何服务的生命周期都不会启动。 简单说就是所有的 StartingAsync方法将首先并行执行,然后StartAsync方法也将并行执行,依此类推。

Tip:当我们的应用程序拥有多个托管服务时,并发启动可缩短启动和关闭的时间。

四、总结

通过 IHostedLifecycleService接口,我们可以更精细地控制每个服务在生命周期阶段启动和停止时发生的情况,可以初始化其他服务所需的依赖关系。 如果我们的应用程序实现了多个托管服务,就需要引入HostOptions来同时启动和停止服务。


http://www.kler.cn/a/304272.html

相关文章:

  • 7天用Go从零实现分布式缓存GeeCache(学习)(3)
  • C++笔记---异常
  • 【C++】详细介绍模版进阶,细节满满
  • Visual Studio Code 端口转发功能详解
  • C++实现用户分组--学习
  • 020_Servlet_Mysql学生选课系统(新版)_lwplus87
  • linux-L3_linux 查看进程(node-red)
  • 如何防止ZIP压缩文件被随意打开?
  • union和union all的区别,别再傻傻分不清楚了!
  • 多模态学习
  • 算法练习题20——猴子选大王(模拟)
  • 【鸿蒙】HarmonyOS NEXT星河入门到实战9-组件化开发进阶应用状态管理
  • [SC]Windows VS2022下配置SystemC环境
  • web前端-HTML常用标签(三)
  • 揭秘线程安全:HashMap 的四大实用策略
  • 树莓派智能语音助手实现音乐播放
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • 海鸥相机存储卡格式化如何恢复数据
  • 工作流技术(WorkFlow)
  • 【系统规划与管理师】【案例分析】【考点】【答案篇】第5章 IT服务部署实施
  • 主机加固的案例应用
  • 前端计算机网络面试基础知识
  • rancker 图形化界面
  • 充电管理芯片
  • Redis简介、常用命令及优化
  • 串口通信协议