日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 3.x控制IHostedService启动顺序浅探

發布時間:2023/12/4 asp.net 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 3.x控制IHostedService启动顺序浅探 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

想寫好中間件,這是基礎。

?

一、前言

今天這個內容,基于于ASP.NET Core 3.x。

從3.x開始,ASP.NET Core使用了通用主機模式。它將WebHostBuilder放到了通用的IHost之上,這樣可以確保Kestrel可以運行在IHostedService中。

我們今天就來研究一下這個啟動方式和啟動順序。

二、通常的啟動次序

通常情況下,IHostedService的任何實現在添加到Startup.ConfigureServices()后,都會在GenericWebHostService之前啟動。

這是微軟官方給出的圖。

這個圖展示了在IHost上調用RunAsync()時的啟動順序(后者又調用StartAsync())。對我們來說,最重要的部分是啟動的IHostedServices。從圖上也可以看到,自定義IHostedServices先于GenericWebHostSevice啟動。

我們來看一個簡單的例子:

public?class?StartupHostedService?:?IHostedService {private?readonly?ILogger?_logger;public?StartupHostedService(ILogger<StartupHostedService>?logger){_logger?=?logger;}public?Task?StartAsync(CancellationToken?cancellationToken){_logger.LogInformation("Starting?IHostedService?registered?in?Startup");return?Task.CompletedTask;}public?Task?StopAsync(CancellationToken?cancellationToken){_logger.LogInformation("Stopping?IHostedService?registered?in?Startup");return?Task.CompletedTask;} }

我們做一個簡單的IHostedService。希望加到Startup.cs中:

public?class?Startup {public?void?ConfigureServices(IServiceCollection?services){services.AddHostedService<StartupHostedService>();} }

運行代碼:

info:?demo.StartupHostedService[0]????????????#?這是上邊的StartupHostedServiceStarting?IHostedService?registered?in?Startup info:?Microsoft.Hosting.Lifetime[0]????????????#?這是GenericWebHostSeviceNow?listening?on:?https://localhost:5001 info:?Microsoft.Hosting.Lifetime[0]Application?started.?Press?Ctrl+C?to?shut?down.

正如預期的那樣,IHostedService首先執行,然后是GenericWebHostSevice。ApplicationLifetime事件在所有IHostedServices執行之后觸發。無論在什么地方注冊了Startup.ConfigureServices()中的IHostedService,?GenericWebHostSevice都在最后啟動。

?

那么問題來了,為什么GenericWebHostSevice在最后啟動?

三、為什么`GenericWebHostSevice`在最后啟動?

先看看多個IHostedService的情況。

當有多個IHostedService的實現加入到Startup.ConfigureServices()時,運行次序取決于它被加入的次序。

看例子:

public?class?Service1?:?IHostedService {private?readonly?ILogger?_logger;public?Service1(ILogger<Service1>?logger){_logger?=?logger;}public?Task?StartAsync(CancellationToken?cancellationToken){_logger.LogInformation("Starting?Service1");return?Task.CompletedTask;}public?Task?StopAsync(CancellationToken?cancellationToken){_logger.LogInformation("Stoping?Service1");return?Task.CompletedTask;} } public?class?Service2?:?IHostedService {private?readonly?ILogger?_logger;public?Service2(ILogger<Service2>?logger){_logger?=?logger;}public?Task?StartAsync(CancellationToken?cancellationToken){_logger.LogInformation("Starting?Service2");return?Task.CompletedTask;}public?Task?StopAsync(CancellationToken?cancellationToken){_logger.LogInformation("Stoping?Service2");return?Task.CompletedTask;} }

Startup.cs:

public?class?Startup {public?void?ConfigureServices(IServiceCollection?services){services.AddHostedService<Service1>();services.AddHostedService<Service2>();} }

運行:

info:?demo.Service1[0]????????????????#?這是Service1Starting?Service1 info:?demo.Service2[0]????????????????#?這是Service2Starting?Service2 info:?Microsoft.Hosting.Lifetime[0]????????#?這是GenericWebHostSeviceNow?listening?on:?https://localhost:5001 info:?Microsoft.Hosting.Lifetime[0]Application?started.?Press?Ctrl+C?to?shut?down.

?

那么,GenericWebHostSevice是什么時候注冊的?

我們看看另一個文件Program.cs:

public?class?Program {public?static?void?Main(string[]?args){CreateHostBuilder(args).Build().Run();}public?static?IHostBuilder?CreateHostBuilder(string[]?args)?=>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder?=>????????????#?這是GenericWebHostSevice注冊的位置{webBuilder.UseStartup<Startup>();}); }

ConfigureWebHostDefaults擴展方法調用ConfigureWebHost方法,該方法執行Startup.ConfigureServices(),然后注冊GenericWebHostService。整理一下代碼,就是下面這個樣子:

public?static?IHostBuilder?ConfigureWebHost(this?IHostBuilder?builder,?Action<IWebHostBuilder>?configure) {var?webhostBuilder?=?new?GenericWebHostBuilder(builder);configure(webhostBuilder);builder.ConfigureServices((context,?services)?=>?services.AddHostedService<GenericWebHostService>());return?builder; }

這樣可以確保GenericWebHostService總是最后運行,以保持通用主機實現和WebHost(已棄用)實現之間的行為一致。

?

因此,可以采用同樣的方式,讓IHostedService在GenericWebHostService后面啟動。

四、讓`IHostedService`在`GenericWebHostService`后面啟動

在大多數情況下,在GenericWebHostService之前啟動IHostedServices就可以滿足常規的應用。但是,GenericWebHostService還負責構建應用程序的中間件管道。如果IHostedService依賴于中間件管道或路由,那么就需要將它的啟動延遲到GenericWebHostService完成之后。

根據上面的說明,在GenericWebHostService之后執行IHostedService的唯一方法是將它添加到GenericWebHostService之后的DI容器中。這意味著你必須跳出Startup.ConfigureServices(),在調用ConfigureWebHostDefaults之后,直接在IHostBuilder上調用ConfigureServices():

public?class?ProgramHostedService?:?IHostedService {private?readonly?ILogger?_logger;public?ProgramHostedService(ILogger<ProgramHostedService>?logger){_logger?=?logger;}public?Task?StartAsync(CancellationToken?cancellationToken){_logger.LogInformation("Starting?ProgramHostedService?registered?in?Program");return?Task.CompletedTask;}public?Task?StopAsync(CancellationToken?cancellationToken){_logger.LogInformation("Stopping?ProgramHostedService?registered?in?Program");return?Task.CompletedTask;} }

加到Program.cs中:

public?class?Program {public?static?void?Main(string[]?args){CreateHostBuilder(args).Build().Run();}public?static?IHostBuilder?CreateHostBuilder(string[]?args)?=>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder?=>????????????#?這是GenericWebHostSevice注冊的位置{webBuilder.UseStartup<Startup>();}).ConfigureServices(services?=>?services.AddHostedService<ProgramHostedService>());????????????#?這是ProgramHostedService注冊的位置 }

看輸出:

info:?demo.StartupHostedService[0]????????????#?這是StartupHostedServiceStarting?IHostedService?registered?in?Startup info:?Microsoft.Hosting.Lifetime[0]????????????#?這是GenericWebHostSeviceNow?listening?on:?https://localhost:5001 info:?demo.ProgramHostedService[0]????????????#?這是ProgramHostedServiceStarting?ProgramHostedService?registered?in?Program info:?Microsoft.Hosting.Lifetime[0]Application?started.?Press?Ctrl+C?to?shut?down.

同樣,在關閉應用時,IHostedServices被反向停止,所以ProgramHostedService首先停止,接著是GenericWebHostSevice,最后是StartupHostedService:

info:?Microsoft.Hosting.Lifetime[0]Application?is?shutting?down... info:?demo.ProgramHostedService[0]Stopping?ProgramHostedService?registered?in?Program info:?demo.StartupHostedService[0]Stopping?IHostedService?registered?in?Startup

五、總結

最后總結一下:

IHostedServices的執行順序與它們在Startup.configureservices()中添加到DI容器中的順序相同。運行偵聽HTTP請求的Kestrel服務器的GenericWebHostSevice總是注冊的IHostedServices之后運行。

要在GenericWebHostSevice之后啟動IHostedService,需要在Program.cs中的IHostBuilder上的ConfigureServices()擴展方法中進行注冊。

(全文完)

本文的代碼在:https://github.com/humornif/Demo-Code/tree/master/0024/demo

總結

以上是生活随笔為你收集整理的ASP.NET Core 3.x控制IHostedService启动顺序浅探的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。