如何将.NET Core的BackgroundService改写为支持长尾词的定时任务实现?

2026-04-11 07:041阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1509个文字,预计阅读时间需要7分钟。

如何将.NET Core的BackgroundService改写为支持长尾词的定时任务实现?

原文链接:https://www.cnblogs.com/ysmc/p/16468560.

如何将.NET Core的BackgroundService改写为支持长尾词的定时任务实现?

在上述文档中,提到使用IHostedService接口实现定时任务,并传送门。其中,有小伙伴提问,为什么不用BackgroundService,个人觉得使用什么更好。

原文连接: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 官网地址:www.blazor.zone

  希望大佬们看到这篇文章,能给项目点个star支持下,感谢各位!

star流程:

1、访问点击项目链接:BootstrapBlazor

2、点击star,如下图,即可完成star,关注项目不迷路:

另外还有两个GVP项目,大佬们方便的话也点下star呗,非常感谢:

  BootstrapAdmin项目地址:
  gitee.com/LongbowEnterprise/BootstrapAdmin

  SliderCaptcha项目地址:
  gitee.com/LongbowEnterprise/SliderCaptcha

交流群(QQ)欢迎加群讨论

   BA & Blazor ①(795206915)        BA & Blazor ②(675147445)

本文共计1509个文字,预计阅读时间需要7分钟。

如何将.NET Core的BackgroundService改写为支持长尾词的定时任务实现?

原文链接:https://www.cnblogs.com/ysmc/p/16468560.

如何将.NET Core的BackgroundService改写为支持长尾词的定时任务实现?

在上述文档中,提到使用IHostedService接口实现定时任务,并传送门。其中,有小伙伴提问,为什么不用BackgroundService,个人觉得使用什么更好。

原文连接: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 官网地址:www.blazor.zone

  希望大佬们看到这篇文章,能给项目点个star支持下,感谢各位!

star流程:

1、访问点击项目链接:BootstrapBlazor

2、点击star,如下图,即可完成star,关注项目不迷路:

另外还有两个GVP项目,大佬们方便的话也点下star呗,非常感谢:

  BootstrapAdmin项目地址:
  gitee.com/LongbowEnterprise/BootstrapAdmin

  SliderCaptcha项目地址:
  gitee.com/LongbowEnterprise/SliderCaptcha

交流群(QQ)欢迎加群讨论

   BA & Blazor ①(795206915)        BA & Blazor ②(675147445)