.NET Core程序启动时,启动一个异步线程执行永久任务

一、为什么需要程序启动时启动一个异步线程执行永久任务

在程序启动时,有时我们需要单独启动一个线程执行一些检查,或者说这个线程一直存在处理一些周期性任务(比如监听队列时)
这时候.net3.x提供了一个接口IHostedServiceIHostedService本身也是异步执行,但是当你需要持续执行一个周期任务(比如监听队列时)的时候需要用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>();

现在启动程序那么就会执行启动一个线程进行持续检查

三、我们看一下IHostedServiceStartup的执行顺序

//首先执行
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里面即可

posted @ 2022-04-08 18:34  没有感情De佩奇  阅读(819)  评论(0编辑  收藏  举报