.NET Core程序启动时,启动一个异步线程执行永久任务
一、为什么需要程序启动时启动一个异步线程执行永久任务
在程序启动时,有时我们需要单独启动一个线程执行一些检查,或者说这个线程一直存在处理一些周期性任务(比如监听队列时)
这时候.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
里面即可