在业务场景中常常须要后台服务不停的或定时处理一些任务,这些任务是不须要及时响应请求的。
在 asp.net中会使用windows服务来处理。
在 asp.net core中,可使用托管服务来实现,托管服务是一个类,具备实现IHostService接口的后台任务逻辑。git
使用NUGET添加Microsoft.Extensions.Hosting包到项目中
Microsoft.Extensions.Hosting包地址github
取消令牌具备默认的五秒超时,以指示关闭过程再也不是正常的。在令牌上请求取消时:windows
应该停止应用正在执行的任何剩余后台操做。
任何调用的方法都StopAsync应该当即返回。
可是,在请求取消后,任务不会被放弃 - 调用者等待全部任务完成。服务器
若是应用程序被意外关闭(例如,应用程序的进程失败),则StopAsync可能没法调用。所以,StopAsync是有可能不会被调用的。asp.net
托管服务在应用启动时激活一次,并在应用关闭时正常关闭。为防止异常,最好继承IDispose接口,释放资源async
能够写一个托管服务类直接继承IHostedService,和IDisposable接口ide
public class MyTimerHostedService : IHostedService, IDisposable { private Timer _timer; public Task StartAsync(CancellationToken cancellationToken) { Console.WriteLine("启动定时任务托管服务"); _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(0.5)); return Task.CompletedTask; } private void DoWork(object state) { Console.WriteLine("定时任务处理中"); } public Task StopAsync(CancellationToken cancellationToken) { _timer?.Change(Timeout.Infinite, 0); Console.WriteLine("中止定时任务"); return Task.CompletedTask; } public void Dispose() { // 手动释放定时器 _timer?.Dispose(); } }
该服务Startup.ConfigureServices使用AddHostedService扩展方法注册:函数
services.AddHostedService<MyTimerHostedService>();
class Program { static void Main(string[] args) { var host = new HostBuilder().ConfigureServices((hostContext, services) => { services.AddHostedService<MyTimerHostedService>(); }).Build(); host.Run(); Console.WriteLine("Hello World!"); Console.ReadLine(); } }
.NET Core中实现的抽象BackgroundService基类。ui
// Copyright (c) .NET Foundation. Licensed under the Apache License, Version 2.0. /// <summary> /// Base class for implementing a long running <see cref="IHostedService"/>. /// </summary> public abstract class BackgroundService : IHostedService, IDisposable { private Task _executingTask; private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource(); protected abstract Task ExecuteAsync(CancellationToken stoppingToken); public virtual Task StartAsync(CancellationToken cancellationToken) { // Store the task we're executing _executingTask = ExecuteAsync(_stoppingCts.Token); // If the task is completed then return it, // this will bubble cancellation and failure to the caller if (_executingTask.IsCompleted) { return _executingTask; } // Otherwise it's running return Task.CompletedTask; } public virtual async Task StopAsync(CancellationToken cancellationToken) { // Stop called without start if (_executingTask == null) { return; } try { // Signal cancellation to the executing method _stoppingCts.Cancel(); } finally { // Wait until the task completes or the stop token triggers await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken)); } } public virtual void Dispose() { _stoppingCts.Cancel(); } }
因为抽象类已经实现了IHostService接口定义的方法,只须要写子类去继承BackgroundService, 在本身的自定义托管服务类中实现ExecuteAsync()方法this
public class MyBackGroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { Console.WriteLine("MyBackGroundService doing"); //延迟500毫秒执行 至关于使用了定时器 await Task.Delay(500, stoppingToken); } } }
在主机中托管服务
class Program { static void Main(string[] args) { var host = new HostBuilder().ConfigureServices((hostContext, services) => { //services.AddHostedService<MyTimerHostedService>(); services.AddHostedService<MyBackGroundService>(); }).Build(); host.Run(); Console.WriteLine("Hello World!"); Console.ReadLine(); } }
使用了HostService后极大的方便了后台任务的管理