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