谈谈.NET Core中基于Generic Host来实现后台任务 (4)

如果我们只是纯綷的把实现代码放到StartAsync方法中,那么可能就会有惊喜了。

public class PrinterHostedService : IHostedService, IDisposable { //other .... public async Task StartAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { Console.WriteLine("Printer is working."); await Task.Delay(TimeSpan.FromSeconds(_settings.PrinterDelaySecond), cancellationToken); } } public Task StopAsync(CancellationToken cancellationToken) { Console.WriteLine("Printer is stopped"); return Task.CompletedTask; } }

运行之后,想用ctrl+c来停止,发现还是一直在跑。

谈谈.NET Core中基于Generic Host来实现后台任务

ps一看,这个进程还在,kill掉之后才不会继续输出。。

谈谈.NET Core中基于Generic Host来实现后台任务

问题出在那里呢?原因其实还是比较明显的,因为这个任务还没有启动成功,一直处于启动中的状态!

换句话说,StartAsync方法还没有执行完。这个问题一定要小心再小心。

要怎么处理这个问题呢?解决方法也比较简单,可以通过引用一个变量来记录要运行的任务,将其从StartAsync方法中解放出来。

public class PrinterHostedService3 : IHostedService, IDisposable { //others ..... private bool _stopping; private Task _backgroundTask; public Task StartAsync(CancellationToken cancellationToken) { Console.WriteLine("Printer3 is starting."); _backgroundTask = BackgroundTask(cancellationToken); return Task.CompletedTask; } private async Task BackgroundTask(CancellationToken cancellationToken) { while (!_stopping) { await Task.Delay(TimeSpan.FromSeconds(_settings.PrinterDelaySecond),cancellationToken); Console.WriteLine("Printer3 is doing background work."); } } public Task StopAsync(CancellationToken cancellationToken) { Console.WriteLine("Printer3 is stopping."); _stopping = true; return Task.CompletedTask; } public void Dispose() { Console.WriteLine("Printer3 is disposing."); } }

这样就能让这个任务真正的启动成功了!效果就不放图了。

相对来说,BackgroundService用起来会比较简单,实现核心的ExecuteAsync这个抽象方法就差不多了,出错的概率也会比较低。

IHostBuilder的扩展写法

在注册服务的时候,我们还可以通过编写IHostBuilder的扩展方法来完成。

public static class Extensions { public static IHostBuilder UseHostedService<T>(this IHostBuilder hostBuilder) where T : class, IHostedService, IDisposable { return hostBuilder.ConfigureServices(services => services.AddHostedService<T>()); } public static IHostBuilder UseComsumeRabbitMQ(this IHostBuilder hostBuilder) { return hostBuilder.ConfigureServices(services => services.AddHostedService<ComsumeRabbitMQHostedService>()); } }

使用的时候就可以像下面一样。

var builder = new HostBuilder() //others ... .ConfigureServices((hostContext, services) => { services.AddOptions(); services.Configure<AppSettings>(hostContext.Configuration.GetSection("AppSettings")); //basic usage //services.AddHostedService<PrinterHostedService2>(); //services.AddHostedService<TimerHostedService>(); //services.AddHostedService<ComsumeRabbitMQHostedService>(); }) //extensions usage .UseComsumeRabbitMQ() .UseHostedService<TimerHostedService>() .UseHostedService<PrinterHostedService2>() //.UseHostedService<ComsumeRabbitMQHostedService>() ; 总结

Generic Host让我们可以用熟悉的方式来处理后台任务,不得不说这是一个很

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwwwy.html