一、為什么需要程序啟動時啟動一個異步線程執行永久任務
在程序啟動時,有時我們需要單獨啟動一個線程執行一些檢查,或者說這個線程一直存在處理一些周期性任務(比如監聽隊列時)
這時候.net3.x提供了一個接口IHostedService
,IHostedService
本身也是異步執行,但是當你需要持續執行一個周期任務(比如監聽隊列時)的時候需要用Task.Run
開啟一個線程進行處理
二、IHostedService怎么使用,怎么創建一個持續周期任務
我們先看一下IHostedService有哪些接口
//
// 摘要:
// Defines methods for objects that are managed by the host.
public interface IHostedService
{
//
// 摘要:
// Triggered when the application host is ready to start the service.
//
// 參數:
// cancellationToken:
// Indicates that the start process has been aborted.
Task StartAsync(CancellationToken cancellationToken);
//
// 摘要:
// Triggered when the application host is performing a graceful shutdown.
//
// 參數:
// cancellationToken:
// Indicates that the shutdown process should no longer be graceful.
Task StopAsync(CancellationToken cancellationToken);
}
StartAsync
用於程序准備好啟動服務時執行,StopAsync
用於程序正常關閉時執行
現在我們先實現IHostedService
(假如我們程序啟動時需要一個線程來持續執行檢查是否有賬戶數據)
public class StartRunHostService : IHostedService
{
public IAccBLL AccBLL { get; set; }
public StartRunHostService(IAccBLL _AccBLL)
{
AccBLL=_AccBLL;
}
public Task StartAsync(CancellationToken cancellationToken)
{
//進行賬戶檢查,方法內部用while循環持續檢查,可用sleep進行沉睡間隔
//不可自己在StartAsync里面直接循環,那樣會導致無法啟動程序
Task.Run(() => AccBLL.AccBLLEntry(Configs.CpnID));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
IHostedService
中我們也可以使用DI容器當中的服務注入其它類使用
IHostedService
實現后我們只需要在Startup.ConfigureServices
中注入即可
services.AddHostedService<StartRunHostService>();
現在啟動程序那么就會執行啟動一個線程進行持續檢查
三、我們看一下IHostedService
在Startup
的執行順序
//首先執行
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersAsServices();
services.AddHostedService<StartRunHostService>();
}
//接着執行
public void ConfigureContainer(ContainerBuilder builder)
{
}
// 中間執行StartRunHostService的StartAsync
// 最后執行
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints();
}
可以看出StartAsync
是我們所有服務加載完成后再執行的,有個問題就是執行的時候我們的中間件管道沒有准備好,但是這個問題不大,很少有什么任務需要我們必須用到中間件管道的
另外其實我們啟動時Configure等操作也是由IHostedService
實現的,所以我們可以通過實現更多的IHostedService
來做更多的任務
好了,到此結束,菜鳥的見解有不對之處煩請指出
補充
后面發現微軟封裝了一個BackgroundService
來做后台任務,通過名字我們也可知道它是做什么的,BackgroundService
也是繼承IHostedService
我們看一下BackgroundService
的內容
//
// 摘要:
// Base class for implementing a long running Microsoft.Extensions.Hosting.IHostedService.
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executingTask;
private CancellationTokenSource _stoppingCts;
//
// 摘要:
// This method is called when the Microsoft.Extensions.Hosting.IHostedService starts.
// The implementation should return a task that represents the lifetime of the long
// running operation(s) being performed.
//
// 參數:
// stoppingToken:
// Triggered when Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)
// is called.
//
// 返回結果:
// A System.Threading.Tasks.Task that represents the long running operations.
protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
//
// 摘要:
// Triggered when the application host is ready to start the service.
//
// 參數:
// cancellationToken:
// Indicates that the start process has been aborted.
public virtual Task StartAsync(CancellationToken cancellationToken)
{
_stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
_executingTask = ExecuteAsync(_stoppingCts.Token);
if (_executingTask.IsCompleted)
{
return _executingTask;
}
return Task.CompletedTask;
}
//
// 摘要:
// Triggered when the application host is performing a graceful shutdown.
//
// 參數:
// cancellationToken:
// Indicates that the shutdown process should no longer be graceful.
[AsyncStateMachine(typeof(_003CStopAsync_003Ed__4))]
public virtual Task StopAsync(CancellationToken cancellationToken)
{
_003CStopAsync_003Ed__4 stateMachine = default(_003CStopAsync_003Ed__4);
stateMachine._003C_003Et__builder = AsyncTaskMethodBuilder.Create();
stateMachine._003C_003E4__this = this;
stateMachine.cancellationToken = cancellationToken;
stateMachine._003C_003E1__state = -1;
stateMachine._003C_003Et__builder.Start(ref stateMachine);
return stateMachine._003C_003Et__builder.Task;
}
//
// 摘要:
// Performs application-defined tasks associated with freeing, releasing, or resetting
// unmanaged resources.
public virtual void Dispose()
{
_stoppingCts?.Cancel();
}
protected BackgroundService()
{
}
}
BackgroundService
里面新增了ExecuteAsyn
,我們的任務就放在ExecuteAsyn
里面即可