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個女朋友!!!!");
}
}