查看: 102|回复: 0

.NET Core 实现定时任务 BackgroundService

[复制链接]

4

主题

9

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2023-3-25 15:22:17 | 显示全部楼层 |阅读模式
前言

在上一篇文档中说到使用 IHostedService 接口实现定时任务传送门:https://www.cnblogs.com/ysmc/p/16456787.html,其中,有小伙伴就问到,为什么不使用 BackgroundService,我个人觉得使用什么技术,应该取决于需求,代码只是一种工具,用得顺手对于编码人员来说,我个人感觉还是非常重要的;正好也说到了 BackgroundService,那这一篇文档就简单说一下它吧。
正文
首先我们看一下官方的说明,学习代码一定要看官方的文档,尽管有时候会有点晦涩难懂,但肯定是最正确的:
BackgroundService 基类
BackgroundService 是用于实现长时间运行的 IHostedService 的基类。
调用 ExecuteAsync(CancellationToken) 来运行后台服务。实现返回一个 Task,其表示后台服务的整个生存期。
在 ExecuteAsync 变为异步(例如通过调用await)之前,不会启动任何其他服务。避免在ExecuteAsync中执行长时间的阻塞初始化工作。
StopAsync(CancellationToken) 中的主机块等待完成ExecuteAsync。
调用 IHostedService.StopAsync 时,将触发取消令牌。当激发取消令牌以便正常关闭服务时,ExecuteAsync的实现应立即完成。否则,服务将在关闭超时后不正常关闭。
StartAsync应仅限于短期任务,因为托管服务是按顺序运行的,在StartAsync运行完成之前不会启动其他服务。长期任务应放置在ExecuteAsync中。
针对第一点“BackgroundService 是用于实现长时间运行的 IHostedService 的基类”,我们先看看 BackgroundService 的源码:
publicabstractclassBackgroundService:IHostedService,IDisposable{privateTask_executingTask;privatereadonlyCancellationTokenSource_stoppingCts=newCancellationTokenSource();///<summary>///Thismethodiscalledwhenthe<seecref="IHostedService"/>starts.Theimplementationshouldreturnataskthatrepresents///thelifetimeofthelongrunningoperation(s)beingperformed.//////</summary>///<paramname="stoppingToken">Triggeredwhen<seecref="IHostedService.StopAsync(CancellationToken)"/>iscalled.</param>///<returns>A<seecref="Task"/>thatrepresentsthelongrunningoperations.</returns>protectedabstractTaskExecuteAsync(CancellationTokenstoppingToken);///<summary>///Triggeredwhentheapplicationhostisreadytostarttheservice.///</summary>///<paramname="cancellationToken">Indicatesthatthestartprocesshasbeenaborted.</param>publicvirtualTaskStartAsync(CancellationTokencancellationToken){//Storethetaskwe'reexecuting_executingTask=ExecuteAsync(_stoppingCts.Token);//Ifthetaskiscompletedthenreturnit,thiswillbubblecancellationandfailuretothecallerif(_executingTask.IsCompleted){return_executingTask;}//Otherwiseit'srunningreturnTask.CompletedTask;}///<summary>///Triggeredwhentheapplicationhostisperformingagracefulshutdown.///</summary>///<paramname="cancellationToken">Indicatesthattheshutdownprocessshouldnolongerbegraceful.</param>publicvirtualasyncTaskStopAsync(CancellationTokencancellationToken){//Stopcalledwithoutstartif(_executingTask==null){return;}try{//Signalcancellationtotheexecutingmethod_stoppingCts.Cancel();}finally{//WaituntilthetaskcompletesorthestoptokentriggersawaitTask.WhenAny(_executingTask,Task.Delay(Timeout.Infinite,cancellationToken));}}publicvirtualvoidDispose(){_stoppingCts.Cancel();}}以上代码很好的解答了小伙伴提出“为什么不使用 BackgroundService”的问题,在上一篇文章中,评论区的一位大佬也很好的回答了这位小伙伴的问题,我这里引用下这位大佬的原话:“BackgroundService 是 IHostedService的一个简单实现,内部IHostedService 的StartAsync调用了ExecuteAsync”,本质上就是使用了 IHostedService;
让我们回到正题,怎么用 BackgroundService 实现定时任务呢,老规矩,上代码:
首先,创建一个服务接口,定义需要实现的任务,以及对应的实现,如果需要执行异步方法,记得加上 await,不然任务将不会等待执行结果,直接进行下一个任务。
publicclassTaskWorkService:ITaskWorkService{publicasyncTaskTaskWorkAsync(CancellationTokenstoppingToken){while(!stoppingToken.IsCancellationRequested){//执行任务Console.WriteLine($"{DateTime.Now}");//周期性任务,于上次任务执行完成后,等待5秒,执行下一次任务awaitTask.Delay(500);}}}注册服务

builder.Services.AddScoped<ITaskWorkService,TaskWorkService>();创建后台服务类,继承基类 BackgroundService,这里需要注意的是,要在 BackgroundService 中使用有作用域的服务,请创建作用域, 默认情况下,不会为托管服务创建作用域,得自己管理服务的生命周期,切记!于构造函数中注入 IServiceProvider即可。
publicclassBackgroundServiceDemo:BackgroundService{privatereadonlyIServiceProvider_services;publicBackgroundServiceDemo(IServiceProviderservices){_services=services;}protectedoverrideasyncTaskExecuteAsync(CancellationTokenstoppingToken){usingvarscope=_services.CreateScope();vartaskWorkService=scope.ServiceProvider.GetRequiredService<ITaskWorkService>();awaittaskWorkService.TaskWorkAsync(stoppingToken);}}最后别忘了这个类也是需要注册的,注册方式与 IHostedService 接口的方式一样
builder.Services.AddHostedService<BackgroundServiceDemo>();大功告成,F5看看效果吧


最后

Bootstrap Blazor官网地址:https://www.blazor.zone,希望大佬们看到这篇文章,能给项目点个star支持下,感谢各位!
转自:一事冇诚
链接:http://cnblogs.com/ysmc/p/16468560.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表