.NET 8 引入了一個(gè)新的接口,叫做IHostedLifecycleService,這個(gè)接口繼承自現(xiàn)有的 IHostedService 接口,它為 BackgroundService 提供了一些新的生命周期事件的方法:
這些方法都發(fā)生在現(xiàn)有的 StartAsync 和 StopAsync 方法之前或之后。
下面的示例演示如何使用新 API:
var builder = Host.CreateApplicationBuilder(args);builder.Services.AddHostedService<MyIOWorker>();var host = builder.Build();host.Run();public class MyIOWorker : BackgroundService, IHostedLifecycleService{ public async Task StartingAsync(CancellationToken cancellationToken) { Console.WriteLine($"{nameof(MyIOWorker)} Starting");//業(yè)務(wù)邏輯 } public async Task StartedAsync(CancellationToken cancellationToken) { Console.WriteLine($"{nameof(MyIOWorker)} Started");//業(yè)務(wù)邏輯 } public async Task StoppingAsync(CancellationToken cancellationToken) { Console.WriteLine($"{nameof(MyIOWorker)} Stopping");//業(yè)務(wù)邏輯 } public async Task StoppedAsync(CancellationToken cancellationToken) { Console.WriteLine($"{nameof(MyIOWorker)} Stopped");//業(yè)務(wù)邏輯 } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { Console.WriteLine($"{nameof(MyIOWorker)} Execute");//業(yè)務(wù)邏輯 await Task.Delay(1000, stoppingToken); } }}
輸出結(jié)果如下:
MyIOService StartingMyIOService ExecuteMyIOService Started...MyIOService StoppingMyIOService Stopped
但是,直接使用 IHostedService 接口一樣可以實(shí)現(xiàn)相同功能:
public class MyIOWorker : BackgroundService{ public override async Task StartAsync(CancellationToken cancellationToken) { Console.WriteLine($"{nameof(MyIOWorker)} Starting");//業(yè)務(wù)邏輯 await base.StartAsync(cancellationToken); Console.WriteLine($"{nameof(MyIOWorker)} Started");//業(yè)務(wù)邏輯 } public override async Task StopAsync(CancellationToken cancellationToken) { Console.WriteLine($"{nameof(MyIOWorker)} Stopping");//業(yè)務(wù)邏輯 await base.StopAsync(cancellationToken); Console.WriteLine($"{nameof(MyIOWorker)} Stopped");//業(yè)務(wù)邏輯 } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { Console.WriteLine($"{nameof(MyIOWorker)} ExecuteAsync");//業(yè)務(wù)邏輯 await Task.Delay(1000, stoppingToken); } }}
那么,新特性IHostedLifecycleService的意義何在呢?
僅僅為了,方便放置不同邏輯的代碼嗎?
在dotnet/runtime源碼https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs中,我們找到了 IHostedLifecycleService 的使用邏輯:
// Call StartingAsync().if (_hostedLifecycleServices is not null){ await ForeachService(_hostedLifecycleServices, cancellationToken, concurrent, abortOnFirstException, exceptions, (service, token) => service.StartingAsync(token)).ConfigureAwait(false); // Exceptions in StartingAsync cause startup to be aborted. LogAndRethrow();}// Call StartAsync().await ForeachService(_hostedServices, cancellationToken, concurrent, abortOnFirstException, exceptions, async (service, token) => { await service.StartAsync(token).ConfigureAwait(false); if (service is BackgroundService backgroundService) { _ = TryExecuteBackgroundServiceAsync(backgroundService); } }).ConfigureAwait(false);// Exceptions in StartAsync cause startup to be aborted.LogAndRethrow();// Call StartedAsync().if (_hostedLifecycleServices is not null){ await ForeachService(_hostedLifecycleServices, cancellationToken, concurrent, abortOnFirstException, exceptions, (service, token) => service.StartedAsync(token)).ConfigureAwait(false);}
上面的代碼先遍歷執(zhí)行IEnumerable<IHostedLifecycleService>? _hostedLifecycleServices的StartingAsync方法,再遍歷執(zhí)行IEnumerable<IHostedService>? _hostedServices的StartAsync方法。
也就是說,如果存在多個(gè)IHostedLifecycleService實(shí)現(xiàn),我們可以把初始化代碼放在StartingAsync方法實(shí)現(xiàn)中,保證了全部初始化邏輯執(zhí)行成功后才會執(zhí)行StartAsync方法中正式的業(yè)務(wù)邏輯。對于StopAsync方法也是同理。
比如,如果直接使用 IHostedService 接口:
builder.Services.AddHostedService<AWorker>();builder.Services.AddHostedService<BWorker>();public class AWorker : BackgroundService{ public override async Task StartAsync(CancellationToken cancellationToken) { //初始化數(shù)據(jù)庫A表 } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //訪問數(shù)據(jù)庫A表和B表 }}public class BWorker : BackgroundService{ public override async Task StartAsync(CancellationToken cancellationToken) { //初始化數(shù)據(jù)庫B表 } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //訪問數(shù)據(jù)庫A表和B表 }}
由于執(zhí)行有先后順序,初始化數(shù)據(jù)庫B表操作還沒有執(zhí)行,AWorker 就已經(jīng)開始執(zhí)行ExecuteAsync方法了,AWorker 的訪問數(shù)據(jù)庫A表和B表操作可能產(chǎn)生不可預(yù)料的結(jié)果。
現(xiàn)在使用IHostedLifecycleService,將初始化放在生命周期的早期:
public class AWorker : BackgroundService, IHostedLifecycleService{ public async Task StartingAsync(CancellationToken cancellationToken) { //初始化數(shù)據(jù)庫A表 } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //訪問數(shù)據(jù)庫A表和B表 }}public class BWorker : BackgroundService, IHostedLifecycleService{ public async Task StartingAsync(CancellationToken cancellationToken) { //初始化數(shù)據(jù)庫B表 } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //訪問數(shù)據(jù)庫A表和B表 }}
現(xiàn)在,訪問數(shù)據(jù)庫A表和B表操作可以保證正常執(zhí)行了。
默認(rèn)情況下,多個(gè)IHostedLifecycleService實(shí)現(xiàn)是按順序執(zhí)行的,我們還可以設(shè)置它們并發(fā)啟動和停止,節(jié)約整體啟動時(shí)間:
builder.Services.Configure<HostOptions>(options =>{ options.ServicesStartConcurrently = true; options.ServicesStopConcurrently = true;});
IHostedLifecycleService是.NET 8中引入的一個(gè)新特性,它可以讓我們在使用多個(gè)IHostedService實(shí)現(xiàn)的時(shí)候,更加靈活和高效地控制它們的啟動和停止,避免出現(xiàn)不必要的依賴和沖突。
本文鏈接:http://www.www897cc.com/showinfo-26-56563-0.html.NET 8 的 IHostedLifecycleService 接口是雞肋功能嗎?
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: Pulsar3.0新功能,你了解了嗎?
下一篇: 如何提高 Java 代碼的可重用性