BackgroundService 大佬教的好

晨曦001發表於2020-11-29

BackgroundService 原始碼分析

因為換了工作也有兩個多月沒有寫部落格啦,因為跟著紅超哥(大佬)一直在學習和做專案(反正就是在潛心修煉,大佬每天也是在我十萬個為什麼中度過的。)

  • 最近在做一個接收服務端資訊的專案,使用TCP建立連線,雙方進行資訊通訊。後面我會陸陸續續的把自己學習的東西進行一個是輸出。
  • 當時有一個需求需要在程式初始化完畢之後,執行一些不干擾主要流程的程式碼 (說時猛,那時快,聰明的我馬上想到了新起一個執行緒去執行)。
    // 類似於這樣寫
    Task.Run(() =>
    {
        Console.WriteLine("年輕人");
      }).Start();

很快啊 很快,紅超哥就眼神就不對了,完了,完了。當時我就知道紅超哥又要教我了。果不其然紅超哥和我說可以使用BackgroundService也就是今天的主角。

當時我滿腦子都在想一個劇情
紅超哥:年輕人你這樣寫程式碼不優雅,可讀性不好,你在這裡練死勁沒用。
我:有用! 特別有用
...... (後面我沒用)ps:上劇情純屬玩笑

BackgroundService是什麼

  • 但是我看到這名字就知道不簡單了,Background背後+Service服務==背後的幹活
  • 其實也就是我們理解的字面意思,BackgroundService是一個抽象類,繼承IHostedService然後就擁有了StartAsync()、StopAsync()方法。
  • 當我們繼承BackgroundService之後需要重寫ExecuteAsync抽象方法,然後我們只需要在ExecuteAsync方法中寫入自己需要執行的方法就可以了。
  • 然後在配置服務中心注入該方法就可以了services.AddHostedService();,
  • 你就已經完成來了自己的任務了,是不是感覺很簡單呢?(逐漸了忘記了標題)

BackgroundService實現方式

  • 我們通過F12可以進入原始碼中檢視,整體的程式碼結構。繼承IHostedService之後實現了StartAsync()、StopAsync()方法,但是多了一個ExecuteAsync方法和_executingTask欄位、CancellationTokenSource標記
  • _executingTask是一個執行緒變數,主要用於儲存非同步ExecuteAsync方法
  • CancellationTokenSource標記源,這個我在Task博文中介紹過,用於取消執行緒進行。
  • 重點說一下StartAsync會在程式所有配置載入完之後才會執行。

BackgroundService擴充

現在我們要實現一個輪詢需求,我們需要怎麼做呢?(此時此刻我想望向紅超哥,但是我一個人出差了,所以只能自己實現了)

       public abstract class InitBackgroundWork : BackgroundService
       {
              //建立一個取消標記源
              private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

              //入參委託
              private Action<object> action;

              //方法初始話
              protected void Init()
              {
                     action = async e =>
                     {
                           while (true)
                           {
                                  DoWork(e);
                                  await Task.Delay(TimeSpan.FromSeconds(10));
                           }
                     };
              }

              /// <summary>
              /// 執行方法
              /// </summary>
              /// <param name="stoppingToken"></param>
              /// <returns></returns>
              protected override Task ExecuteAsync(CancellationToken stoppingToken)
              {
                     Init();
                     _ = Task.Factory.StartNew(action, cancellationTokenSource.Token);
                     return Task.CompletedTask;
              }

              /// <summary>
              /// 我們重寫一下關閉方法
              /// </summary>
              /// <param name="cancellationToken"></param>
              /// <returns></returns>
              public override Task StopAsync(CancellationToken cancellationToken)
              {
                     cancellationTokenSource.Cancel();
                     return base.StopAsync(cancellationToken);
              }

              //丟擲方法入口
              protected abstract void DoWork(object state);
       }

這樣我們只需要管入口方法就好了,建立一個類繼承它,然後在配置服務中AddHostedService新增就好了,我們也可以直接通過開始方法、結束方法控制就好了

       public class  GetGirlfriend: InitBackgroundWork
       {
              protected override void DoWork(object state)
              {
                     Console.WriteLine("給我1個女朋友!!!!");
              }
       }

最後總結願望成真

相關文章