
這是在Asp.Net Core 2.1加入了一種新的Host,現在2.1版本的Asp.Net Core中,有了兩種可用的Host。
Web Host –适用于托管Web程式的Host,就是我們所熟悉的在Asp.Net Core應用程式的Mai函數中用CreateWebHostBuilder建立出來的常用的WebHost。
Generic Host (ASP.NET Core 2.1版本才有) – 适用于托管非 Web 應用(例如,運作背景任務的應用)。 在未來的版本中,通用主機将适用于托管任何類型的應用,包括 Web 應用。 通用主機最終将取代 Web 主機,這大概也是這種類型的主機叫做通用主機的原因,在本部落格中,我們将結合源碼,讨論通用主機的工作原理。
通用主機,讓我可以用編寫Asp.Net Core的思想(例如控制反轉、依賴注入、IOC容器)來簡化控制台應用程式的建立(個人見解),主機負責程式的啟動和生存周期的管理,這對于不處理HTTP請求的應用程式非常有用(處理HTTP請求的是Web應用程式,用Web Host托管),通用主機的目标是将HTTP管道從Web Host中脫離出來,使得Asp.Net Core的那套東西也适用于其他.Net Core程式。
在開始跟随我分析通用主機之前,大家可以到Github下載下傳這個官方Demo。
https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/host/generic-host/samples/
如果覺得下載下傳一整個比較慢,可以從我的這個Github倉庫下載下傳,沒有其他多餘内容,國内Github比較慢,如果你從官方那個倉庫下載下傳可能會需要很長時間甚至失敗。
https://github.com/liuzhenyulive/Generic-Host-Demo
首先,大家打開下載下傳下來的這個官方Demo,進入Main函數。
可以看到,這簡直就是一個精簡版的Asp.Net Core應用程式,對這個Main函數中出現的所有方法,大家對Asp.Net Core Web應用程式比較熟悉,是以我與Asp.net core 的Webhost做了一個對比,來幫助大家找找感覺。
通用主機
Web主機
new HostBuilder()
WebHost.CreateDefaultBuilder(args)
ConfigureAppConfiguration
(用于配置Configuration)
WebHost也有這個方法,隻是大家預設可能沒有調用。
ConfigureServices
(用于配置Service,也就是依賴注入)
WebHost其實也有ConfigureServices方法,可以這麼調用。
但是我們一般很少這麼用,一般都是放在Startup的ConfigureServices方法中進行依賴注入。
ConfigureLogging
(是本應用程式所需要的配置,非必需)
WebHost還是有!
builder.RunConsoleAsync()
RunConsoleAsync中其實是對hostbuilder進行
Builder然後Run
CreateWebHostBuilder(args).Build().Run();
也就是Main函數中的Build().Run();
無無無無
Startup中的Configure()方法
Asp.net core在此方法中進行Http請求管道的配置
綜上對比,我做了如下概括!
通用主機(Generic Host)有的 Web Host都有。
Web Host的Http Pipeline即Startup.Configure() 在通用主機中沒有。
這就應證了開頭所說的:通用主機的目标是将HTTP管道從Web Host中脫離出來,使得Asp.Net Core的那套東西也适用于其他.Net Core程式。
我覺得要知道怎麼用,那麼我們就首先要知道Host的Run方法内到底是在執行什麼?
是以我們深入源碼,一路F12!
builder.RunConsoleAsync(); =>hostBuilder.UseConsoleLifetime().Build().RunAsync(cancellationToken);=> await host.StartAsync(token);
總算找到了,最關鍵的在這裡。
this._hostedServices = this.Services.GetService<IEnumerable<IHostedService>>(); foreach (IHostedService hostedService in this._hostedServices) await hostedService.StartAsync(cancellationToken).ConfigureAwait(false
知道大家都喜歡Yellow色,是以我用Yellow把最關鍵的代碼标示出來了,那麼這些代碼有什麼含義呢?
this._hostedServices = this.Services.GetService<IEnumerable<IHostedService>>();
這一行的意思是,從容器中取出所有實作了IHostedService的服務。
這就意味着,我們實作了IHostedService後,需要把該Service注冊到IOC容器中。
foreach (IHostedService hostedService in this._hostedServices)
await hostedService.StartAsync(cancellationToken).ConfigureAwait(false);
執行每個服務的StartAsync方法。
是以,大家是不是冥冥中猜到了怎麼用的呢?
我總結的步驟如下:
自定義一個Service,繼承 IHostedService接口。
實作 IHostedService的StartAsync方法,把需要執行的任務放到這個方法中。
把該服務注冊到IOC容器(ServiceCollection)中。
可以看到,在StartAsync中,定義了一個定時任務,帶定時任務每五秒執行一次DoWork方法。
在DoWork方法中,日志記錄器記錄了一段内容。
因為在Main方法中,對Log進行了如下的配置。
是以,一旦日志記錄了内容,該内容就會在控制台中輸出。
<IHostedService, PrintTextToConsoleService>
黃色部分,把實作了IHostedService接口的PrintTextToConsoleService注冊到容器中。
可以看到,控制台中,每五秒就有一次内容輸出,說明DoWork方法沒五秒被執行了一次,也說明PrintTextToConsoleService的StartAsync被成功調用了。
希望本文對幫助大家了解通用主機能夠有所幫助,如果對.Net Core的源碼分析、潮流新技術感興趣
歡迎關注我
不定期推出實用幹活,謝謝!
參考文獻
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.1