.NET Core 实现后台任务(定时任务)BackgroundService(二)
原文连接:https://www.cnblogs.com/ysmc/p/16468560.html
在上一篇文档中说到使用 IHostedService 接口实现定时任务,其中,有小伙伴就问到,为什么不使用 BackgroundService,我个人觉得使用什么技术,应该取决于需求,代码只是一种工具,用得顺手对于编码人员来说,我个人感觉还是非常重要的;正好也说到了 BackgroundService,那这一篇文档就简单说一下它吧。
首先我们看一下官方的说明,学习代码一定要看官方的文档,尽管有时候会有点晦涩难懂,但肯定是最正确的:
BackgroundService 基类
BackgroundService 是用于实现长时间运行的 IHostedService 的基类。
调用 ExecuteAsync(CancellationToken) 来运行后台服务。 实现返回一个 Task,其表示后台服务的整个生存期。
在 ExecuteAsync 变为异步(例如通过调用 await)之前,不会启动任何其他服务。 避免在 ExecuteAsync 中执行长时间的阻塞初始化工作。
StopAsync(CancellationToken) 中的主机块等待完成 ExecuteAsync。
调用 IHostedService.StopAsync 时,将触发取消令牌。 当激发取消令牌以便正常关闭服务时,ExecuteAsync 的实现应立即完成。 否则,服务将在关闭超时后不正常关闭。
StartAsync 应仅限于短期任务,因为托管服务是按顺序运行的,在 StartAsync 运行完成之前不会启动其他服务。 长期任务应放置在 ExecuteAsync 中。
针对第一点“BackgroundService 是用于实现长时间运行的 IHostedService 的基类”,我们先看看 BackgroundService 的源码:
1 public abstract class BackgroundService : IHostedService, IDisposable
2 {
3 private Task _executingTask;
4 private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();
5
6 /// <summary>
7 /// This method is called when the <see cref="IHostedService"/> starts. The implementation should return a task that represents
8 /// the lifetime of the long running operation(s) being performed.
9 /// /// </summary>
10 /// <param name="stoppingToken">Triggered when <see cref="IHostedService.StopAsync(CancellationToken)"/> is called.</param>
11 /// <returns>A <see cref="Task"/> that represents the long running operations.</returns>
12 protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
13
14 /// <summary>
15 /// Triggered when the application host is ready to start the service.
16 /// </summary>
17 /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
18 public virtual Task StartAsync(CancellationToken cancellationToken)
19 {
20 // Store the task we're executing
21 _executingTask = ExecuteAsync(_stoppingCts.Token);
22
23 // If the task is completed then return it, this will bubble cancellation and failure to the caller
24 if (_executingTask.IsCompleted)
25 {
26 return _executingTask;
27 }
28
29 // Otherwise it's running
30 return Task.CompletedTask;
31 }
32
33 /// <summary>
34 /// Triggered when the application host is performing a graceful shutdown.
35 /// </summary>
36 /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
37 public virtual async Task StopAsync(CancellationToken cancellationToken)
38 {
39 // Stop called without start
40 if (_executingTask == null)
41 {
42 return;
43 }
44
45 try
46 {
47 // Signal cancellation to the executing method
48 _stoppingCts.Cancel();
49 }
50 finally
51 {
52 // Wait until the task completes or the stop token triggers
53 await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
54 }
55
56 }
57
58 public virtual void Dispose()
59 {
60 _stoppingCts.Cancel();
61 }
62 }
以上代码很好的解答了小伙伴提出“为什么不使用 BackgroundService”的问题,在上一篇文章中,评论区的一位大佬也很好的回答了这位小伙伴的问题,我这里引用下这位大佬的原话:“BackgroundService 是 IHostedService的一个简单实现,内部IHostedService 的StartAsync调用了ExecuteAsync”,本质上就是使用了 IHostedService;
让我们回到正题,怎么用 BackgroundService 实现定时任务呢,老规矩,上代码:
首先,创建一个服务接口,定义需要实现的任务,以及对应的实现,如果需要执行异步方法,记得加上 await,不然任务将不会等待执行结果,直接进行下一个任务。
1 public class TaskWorkService : ITaskWorkService
2 {
3 public async Task TaskWorkAsync(CancellationToken stoppingToken)
4 {
5 while (!stoppingToken.IsCancellationRequested)
6 {
7 //执行任务
8 Console.WriteLine($"{DateTime.Now}");
9
10 //周期性任务,于上次任务执行完成后,等级5秒,执行下一次任务
11 await Task.Delay(500);
12 }
13 }
14 }
注册服务
builder.Services.AddScoped<ITaskWorkService, TaskWorkService>();
创建后台服务类,继承基类 BackgroundService,这里需要注意的是,要在 BackgroundService 中使用有作用域的服务,请创建作用域, 默认情况下,不会为托管服务创建作用域,得自己管理服务的生命周期,切记!于构造函数中注入 IServiceProvider即可。
1 public class BackgroundServiceDemo : BackgroundService
2 {
3 private readonly IServiceProvider _services;
4
5 public BackgroundServiceDemo(IServiceProvider services)
6 {
7 _services = services;
8 }
9
10 protected override async Task ExecuteAsync(CancellationToken stoppingToken)
11 {
12 using var scope = _services.CreateScope();
13
14 var taskWorkService = scope.ServiceProvider.GetRequiredService<ITaskWorkService>();
15
16 await taskWorkService.TaskWorkAsync(stoppingToken);
17 }
18 }
最后别忘了这个类也是需要注册的,注册方式与 IHostedService 接口的方式一样
builder.Services.AddHostedService<BackgroundServiceDemo>();
大功告成,F5看看效果吧

写在最后
Bootstrap Blazor 官网地址:https://www.blazor.zone
希望大佬们看到这篇文章,能给项目点个star支持下,感谢各位!
star流程:
1、访问点击项目链接:BootstrapBlazor
2、点击star,如下图,即可完成star,关注项目不迷路:

另外还有两个GVP项目,大佬们方便的话也点下star呗,非常感谢:
BootstrapAdmin 项目地址:
https://gitee.com/LongbowEnterprise/BootstrapAdmin
SliderCaptcha 项目地址:
https://gitee.com/LongbowEnterprise/SliderCaptcha
交流群(QQ)欢迎加群讨论
BA & Blazor ①(795206915) BA & Blazor ②(675147445)


.NET Core 实现后台任务(定时任务)BackgroundService(二)的更多相关文章
- ASP.NET Core 使用 Hangfire 定时任务
定时任务组件,除了 Hangfire 外,还有一个 Quarz.NET,不过 Hangfire .NET Core 支持的会更好些. ASP.NET Core 使用 Hangfire 很简单,首先,N ...
- Core开发-后台任务利器Hangfire使用
Core开发-后台任务利器Hangfire使用 ASP.NET Core开发系列之后台任务利器Hangfire 使用. Hangfire 是一款强大的.NET开源后台任务利器,无需Windows服务/ ...
- ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)
前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...
- ASP.NET Core 基于JWT的认证(二)
ASP.NET Core 基于JWT的认证(二) 上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用 ...
- .net core 的图片处理及二维码的生成及解析
写代码这事,掐指算来已经十有余年. 从html到css到javascript到vbscript到c#,从兴趣到职业,生活总是失落与惊喜并存. 绝大部分时候,出发并不是因为知道该到哪里去,只是知道不能再 ...
- C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求
C# 动态创建SQL数据库(二) 使用Entity Framework 创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...
- 一张图搞定OAuth2.0 在Office应用中打开WPF窗体并且让子窗体显示在Office应用上 彻底关闭Excle进程的几个方法 (七)Net Core项目使用Controller之二
一张图搞定OAuth2.0 目录 1.引言 2.OAuth2.0是什么 3.OAuth2.0怎么写 回到顶部 1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常 ...
- 使用.NET Core创建Windows服务(二) - 使用Topshelf方式
原文:Creating Windows Services In .NET Core – Part 2 – The "Topshelf" Way 作者:Dotnet Core Tut ...
- 深入理解.NET Core的基元(二) - 共享框架
原文:Deep-dive into .NET Core primitives, part 2: the shared framework 作者:Nate McMaster 译文:深入理解.NET Co ...
- 深入理解.NET Core的基元(二)
原文:Deep-dive into .NET Core primitives, part 2: the shared framework作者:Nate McMaster译文:深入理解.NET Core ...
随机推荐
- 攻防世界-MISC:base64stego
这是攻防世界新手练习区的第十一题,题目如下: 点击下载附件一,发现是一个压缩包,点击解压,发现是需要密码才能解密 先用010editor打开这个压缩包,这里需要知道zip压缩包的组成部分,包括压缩源文 ...
- 龙智被评估为CMMI [3] 级
2022年3月,龙智宣布已被评估为CMMI研究所的能力成熟度模型集成(CMMI)的 [3] 级. CMMI 是一个能力改进框架,它为组织提供有效流程的基本要素,最终提高其绩效. 成熟度级别 3 的评估 ...
- Annotation(注释) _Override _ Deprecated _ SuppressWarnings
Deprecated SuppressWarnings 元注解
- Java 18为什么要指定UTF-8为默认字符集
在Java 18中,将UTF-8指定为标准Java API的默认字符集.有了这一更改,依赖于默认字符集的API将在所有实现.操作系统.区域设置和配置中保持一致. 做这一更改的主要目标: 当Java程序 ...
- 论文解读(GMT)《Accurate Learning of Graph Representations with Graph Multiset Pooling》
论文信息 论文标题:Accurate Learning of Graph Representations with Graph Multiset Pooling论文作者:Jinheon Baek, M ...
- 干货 | Nginx负载均衡原理及配置实例
一个执着于技术的公众号 Nginx系列导读 给小白的 Nginx 10分钟入门指南 Nginx编译安装及常用命令 完全卸载nginx的详细步骤 Nginx 配置文件详解 理解正向代理与反向代理的区别 ...
- ajax、axios、fetch
XMLHttpRequest: XHR中文解释为: 可扩展超文本传输请求:XML可扩展标记语言,Http超文本传输协议,Request请求: XHR对象用于与服务器交换数据,所有现代游览器都支持XHR ...
- Oracle RAC修改监听端口号
目录 修改OracleRAC监听端口号: 1.查看当前数据库监听状态: 2.修改集群监听端口: 3.手动修改LOCAL_LISTENER: 4.停止集群监听和SCAN: 5.修改listener.or ...
- python网络自动化ncclient模块,netconf协议检索与下发交换机配置
以juniper和华为设备为例 交换机必要配置,配置简单,使用ssh模式传输 #juniperset system services netconf ssh#华为 local-user netconf ...
- data:image字符转byte[]
var data = "data:image/bmp;base64,Qk3aHwAAAAAAADYAAAAoAAAAZAAAABsAAAABABgAAAAAAKQfAAAAAQAAAAEAA ...