<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【5min+】后臺任務的積木。.NetCore中的IHostedService

      系列介紹

      【五分鐘的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,比如C#的小細節,AspnetCore,微服務中的.net知識等等。
      5min+不是超過5分鐘的意思,"+"是知識的增加。so,它是讓您花費5分鐘以下的時間來提升您的知識儲備量。

      前言

      這次終于可以給大家分享一些AspNet Core方面的東西了??。雖然本次提及的內容是.NET Core通用,但將以AspNet Core為例作為介紹。

      正文

      咱們開發應用的時候,有時候可能需要建立一些獨立于應用邏輯體本身的后臺任務。比如:定時發送郵件、定時執行腳本這類持續運行的任務,也有驗證數據庫是否創建等只伴隨應用啟動而執行一次的任務。

      在.NET Core 2.0 之后,官方為我們提供了一個叫做 IHostedService 的接口,它可以便于我們更好的實現托管服務。

      在微軟《.NET 微服務 - 體系結構》教程中,就有提及到關于該接口的描述:

      x

      那么今天咱們就來扒一扒 IHostedService 到底是一個怎樣的東西,我們可以在什么情況下使用它。

      前方車速夠快,請抓好扶手。
      x

      IHostService

      請注意 IHostedService 是從 .NET Core 提出的,所以可以看到它并不是專門只針對于 AspNet Core。 從.NetCore 3.x 之后,當大家創建一個新的AspNetCore應用的時候,打開默認的 Program.cs 文件,就會發現它和以往的版本已經不一樣了。

      //現在
      public static IHostBuilder CreateHostBuilder(string[] args) =>
              Host.CreateDefaultBuilder(args)
                  .ConfigureWebHostDefaults(webBuilder =>
                  {
                      webBuilder.UseStartup<Startup>();
                  });
      
      //過去
      public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
              new WebHostBuilder()
                  .UseContentRoot(Directory.GetCurrentDirectory())
                  .UseStartup<Startup>()
                  .UseKestrel()
                  .UseIISIntegration();
      

      可以很明顯的看出應用程序由原來的 IWebHostBuilder 更改為了 IHostBuilder。這就告訴我們,.NET Core進行了更高層次的抽象,也就意味著現在能支持更多不同托管主機的創建方式,未來也將支持更多的類型。果然是一盤很大的棋啊??

      回到今天的主題 IHostedService 。 從命名上來看,就可以看出一些文章。 很明顯,它是伴隨主機一同啟動的任務。因此來看看該接口的簽名:

      public interface IHostedService
      {
          Task StartAsync(CancellationToken cancellationToken);
          Task StopAsync(CancellationToken cancellationToken);
      }
      

      確實,很直觀。只有兩個方法,一個是啟動,一個是停止。也就是說在 Host 啟動的時候,就會調用 StartAsync 方法。在 Host 停止的時候就會調用 StopAsync 方法。

      在AspNet Core中的作用

      那么如果是咱們要在AspNet Core中使用它,該如何操作呢? 首先,咱們先來建立一個實現該接口的類:

      public class DemoHostService : IHostedService
      {
          public async Task StartAsync(CancellationToken cancellationToken)
          {
              await Task.Delay(100);
          }
      
          public Task StopAsync(CancellationToken cancellationToken)
          {
              return Task.CompletedTask;
          }
      }
      

      然后還需要在 Startup.cs 中將它進行注冊:

      services.AddHostedService<DemoHostService>();
      

      OK,就完了。然后應用就會在啟動的時候執行 StartAsync 方法。 咱們可以來斷點試一試,看一看它的啟動順序。 經過斷點之后我們發現基礎的AspNet Core 應用會在執行完成 ConfigureServices 方法之后 再執行 DemoHostServiceStartAsync 方法,最后再執行 Configure 方法:

      // startup.cs
      
      //第一步執行
      public void ConfigureServices(IServiceCollection services)
      {
          services.AddControllers();
          services.AddHostedService<DemoHostService>();
      }
      
      // 中間執行DemoHostService的StartAsync
      
      // 最后執行
      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          app.UseRouting();
          app.UseEndpoints();
      }
      

      就如同下面的示意圖一樣,中間的部分就是咱們自定義的 HostService :

      x

      這就好玩了,說明在應用加載完成所有服務之后,就會在啟動的時候開啟所有的IHostedService 。 那么是否意味著我們可以在自定義的 IHostedService 使用DI容器中的服務呢,或者說在自定義任務中注入其它類。 答案是:肯定的。

      public class DemoHostService : IHostedService
      {
          private IMyServiceDemo serviceDemo;
          public DemoHostService(IMyServiceDemo IServiceDemo)
          {
              serviceDemo = IServiceDemo;
          }
      
          public async Task StartAsync(CancellationToken cancellationToken)
          {
              await Task.Delay(100);
          }
      }
      

      就如同上面一樣,我們使用了注入的IMyServiceDemo類。但是,請注意!!!!IHostedService 的生命周期為單例級別。所以只能在構造函數中注入同為單例級別的服務。而且就算 IHostedService 的周期為其它級別,比如(Scoped),它其實也無法直接在構造函數中注入非單例級別的服務。

      理由是,HostService既然在Configure之前,就證明它目前所在的范圍作用域還是在 “根” 級別上,所以當您注入一個非單例級別的類會提示您“無法在根范圍獲取一個對象”。

      所以如果咱們需要獲取其它生命周期類型服務的時候,就要使用另外一種方法:

      public DemoHostService(IServiceProvider provider)
      {
          var serviceDemo = provider.CreateScope()
                                    .ServiceProvider
                                    .GetService<IMyScpoedService>();
      }
      

      上方只是個快捷寫法,您在使用過程中一定要注意釋放Scope。

      在知道了IHostedService 之后,我們可以來想一想我們能夠在伴隨 Host 啟動時,做一些什么事情呢? 比如,我們在應用啟動時,可以對EFCore進行自動遷移和播種種子數據等:

      public async Task StartAsync(CancellationToken cancellationToken)
      {
          using (var scope = _provider.CreateScope())
          {
              var efContext = scope.ServiceProvider.GetService<MyDbCotext>();
              efContext.Database.EnsureCreated();
      
              // Look for any students.
              if (efContext.Students.Any())
              {
                  return; // DB has been seeded
              }
              else
              {
                  SeedData(efContext);
              }
          }
      }
      

      持續運行的后臺服務

      那么如果我們要定義一個持續運行的后臺任務呢? 比如定時發送郵件等,是否直接在 IHostedServiceStartAsync 中寫個死循環呢? 好吧,答案是否定的。 如果這樣咱們的Host就啟動不起來。 通過查看 .NET Core Host的源代碼就知道,它在最后啟動的時候做了這樣的事情:

      _hostedServices = Services.GetService<IEnumerable<IHostedService>>();
      
      foreach (var hostedService in _hostedServices)
      {
          // Fire IHostedService.Start
          await hostedService.StartAsync(combinedCancellationToken).ConfigureAwait(false);
      }
      

      是的,它用了await關鍵字,也就是說如果直接寫while死循環的話,就會導致一直等待而無法進行下面的操作。所以,我們可以在 IHostedServiceStartAsync 中單獨開一個線程來進行循環:

      public Task StartAsync(CancellationToken cancellationToken)
      {
          new Task(() =>
          {
              while (true)
              {
                  // doing
              }
          });
          return Task.CompletedTask;
      }
      

      當然,.NET Core 早就想到了這一點,所以為我們提供了一個叫做 BackgroundService 的抽象類,我們只需要在 ExecuteAsync 方法中執行特有的邏輯就可以了:

      public class MyBackgroundJob : BackgroundService
      {
          protected override Task ExecuteAsync(CancellationToken stoppingToken)
          {
              while (!stoppingToken.IsCancellationRequested)
              {
                  SendEmail();
              }
          }
      }
      

      總結

      IHostedService 接口為在 ASP.NET Core Web 應用程序(在 .NET Core 2.0 及更高版本中)或任何進程/主機(從使用 IHost 的 .NET Core 2.1 開始)中啟動后臺任務提供了一種便捷方式。 其主要優勢在于,當主機本身將要關閉時,可以有機會進行正常取消以清理后臺任務的代碼。

      其實關于后臺定時任務,您可能會想到一些成熟的框架,比如Hangfire等。當然,它也為.NET Core版本提供了 IHostedService 的實現,您可以從這里看到它的實現

      偷偷告訴您,其實咱們的AspNetCore在啟動時進行初始化Configure 等操作也是通過擴展一個IHostedService來實現的,它的具體實現類叫做:GenericWebHostService

      所以可以看出 IHostedService 為咱們提供了非常便利的操作,我們可以像累積木一樣,往 Host 主機添加我們需要的任務項。就像下面的圖一樣:

      x

      好吧,這次廢話好像多了些。最后,偷偷說一句:創作不易,點個推薦吧.....

      x

      posted @ 2020-02-28 16:07  句幽  閱讀(6804)  評論(12)    收藏  舉報
      主站蜘蛛池模板: 亚洲欧美日韩国产精品专区| 精品粉嫩国产一区二区三区| 国产精品午夜精品福利| 隆德县| 成人午夜免费无码视频在线观看| 国语精品自产拍在线观看网站| 天等县| 久久久久无码精品国产h动漫| 秋霞鲁丝片成人无码| 精品无码日韩国产不卡av| 国产精品中文字幕第一页| 欧美啪啪网| 元码人妻精品一区二区三区9| 亚洲激情一区二区三区在线 | 久久精品国产亚洲综合av| 国产成人久久精品流白浆| xxxxbbbb欧美残疾人| 精品不卡一区二区三区| 99re热视频这里只精品| 一区二区三区av天堂| 极品蜜臀黄色在线观看| 高级艳妇交换俱乐部小说 | 国产对白老熟女正在播放| 国产精品日日摸夜夜添夜夜添无码| 日韩av裸体在线播放| 国产在线98福利播放视频| 99久久无码一区人妻a黑| 免费无码一区无码东京热| 国产午夜福利精品视频| 中文字幕日韩有码第一页| 97香蕉碰碰人妻国产欧美| 欧美做受视频播放| 色欲av亚洲一区无码少妇| 久久亚洲精品成人综合网| 亚洲国产韩国欧美在线| 深夜福利啪啪片| 中文字幕亚洲制服在线看| 国产福利在线观看免费第一福利| 中文无码乱人伦中文视频在线| 中文字幕成熟丰满人妻| 中文字幕国产精品综合|