aspnet core运行后台任务
之前在公司的一个项目中需要用到定时程序,当时使用的是aspnet core提供的ihostedservice接口来实现后台定时程序,具体的示例可去官网查看。现在的dotnet core中默认封装了实现ihostedservice接口的基类backgroundservice,该类实现如下:
// copyright (c) .net foundation. all rights reserved. // licensed under the apache license, version 2.0. see license.txt in the project root for license information. using system; using system.threading; using system.threading.tasks; namespace microsoft.extensions.hosting { /// <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(); /// <summary> /// this method is called when the <see cref="ihostedservice"/> starts. the implementation should return a task that represents /// the lifetime of the long running operation(s) being performed. /// </summary> /// <param name="stoppingtoken">triggered when <see cref="ihostedservice.stopasync(cancellationtoken)"/> is called.</param> /// <returns>a <see cref="task"/> that represents the long running operations.</returns> protected abstract task executeasync(cancellationtoken stoppingtoken); /// <summary> /// triggered when the application host is ready to start the service. /// </summary> /// <param name="cancellationtoken">indicates that the start process has been aborted.</param> 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; } /// <summary> /// triggered when the application host is performing a graceful shutdown. /// </summary> /// <param name="cancellationtoken">indicates that the shutdown process should no longer be graceful.</param> 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(); } } }
根据backgroundservice源码,我们只要实现该类的抽象方法executeasync即可。
可以有两种实现方式来做定时程序,第一种就是实现一个timer:
using microsoft.extensions.hosting; using microsoft.extensions.logging; using system; using system.io; using system.threading; using system.threading.tasks; namespace demoone.models { public class timedbackgroundservice : backgroundservice { private readonly ilogger _logger; private timer _timer; public timedbackgroundservice(ilogger<timedbackgroundservice> logger) { _logger = logger; } protected override async task executeasync(cancellationtoken stoppingtoken) { _timer = new timer(dowork, null, timespan.zero, timespan.fromseconds(5)); _logger.loginformation("周六!"); return task.completedtask; //console.writeline("myservicea is starting."); //stoppingtoken.register(() => file.create($"e:\\dotnetcore\\practice\\practice\\{datetime.now.millisecond}.txt")); //while (!stoppingtoken.iscancellationrequested) //{ // console.writeline("myservicea 开始执行"); // await task.delay(timespan.fromseconds(5), stoppingtoken); // console.writeline("继续执行"); //} //console.writeline("myservicea background task is stopping."); } private void dowork(object state) { _logger.loginformation($"hello world! - {datetime.now}"); } public override void dispose() { base.dispose(); _timer?.dispose(); } } }
我们看看startasync的源码。上面的实现方式会直接返回一个已完成的task,这样就会直接运行startasync方法的if判断,那么如果我们不走if呢?那么就应该由startasync方法返回一个已完成的task.
第二个即是:
using microsoft.extensions.hosting; using microsoft.extensions.logging; using system; using system.io; using system.threading; using system.threading.tasks; namespace demoone.models { public class timedbackgroundservice : backgroundservice { protected override async task executeasync(cancellationtoken stoppingtoken) { console.writeline("myservicea is starting."); stoppingtoken.register(() => file.create($"e:\\dotnetcore\\practice\\practice\\{datetime.now.millisecond}.txt")); while (!stoppingtoken.iscancellationrequested) { console.writeline("myservicea 开始执行"); await task.delay(timespan.fromseconds(5), stoppingtoken); console.writeline("继续执行"); } console.writeline("myservicea background task is stopping."); } public override void dispose() { base.dispose(); } } }
最后我们将实现了backgroundservice的类注入到di即可:
services.addhostedservice<timedbackgroundservice>();
dotnet core的microsoft.extensions.hosting 组件中,充斥着类似ihostedservice接口中定义的方法:startasync、stopasync方法。我们注入的hostedservice服务会在webhost类中通过getrequiredservice获取到注入的定时服务。随后执行startasync方法开始执行。建议看看hosting组件源码,会有很多的收获。
上一篇: 如何使用Spark计算共同好友?
下一篇: 细数中国20年社交红利的诞生与创业雏形
推荐阅读
-
.net core i上 K8S(二)运行简单.netcore程序
-
浅析Linux中使用nohup及screen运行后台任务的示例和区别
-
.net core i上 K8S(三)Yaml文件运行.netcore程序
-
Linux - CentOS 7 安装 .Net Core 运行环境
-
在Asp.Net Core MVC 3.0 视图运行时编译
-
conda pip 安装 dgl 并运行demo 出现:Segmentation fault (core dumped) 错误
-
深入理解Aspnet Core之Identity(2)
-
asp.net core通过控制台启动,设置端口与运行环境
-
在Linux中安装ASPNET.Core3.0运行时
-
[Asp.Net Core] Blazor Server Side 开发教程 - 安装环境与运行第一个程序