.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里面即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM