• .netcore worker service在一个worker里执行多个任务的方法


     最近,有一个项目要使用 Windows 服务,来做为一个软件项目的载体。我想了想,都已经到了跨平台的时代了,会不会有替换 Windows 服务的技术出现呢?于是,在网络上疯狂的搜索了一番,真实皇天不负苦心人,找到了一个答案,那就是 Worker Service。听说在 NET Core 3.0 的时代就新增了 Worker Service 的新项目模板,可以编写长时间运行的后台服务,并且能轻松的部署成 windows 服务或 linux 守护程序。如果安装的 vs2022 是中文版本,Worker Service 的项目名称就变成了辅助角色服务。 

    关于Worker类,既可以写多个,比如 WorkerOne,WorkerTwo 来实现多个任务,也可以在一个Worker类里实现多任务,前者的demo代码如下:

    1. using Furion.TimeCrontab;
    2. namespace WorkerServiceTest
    3. {
    4. public class Worker : BackgroundService
    5. {
    6. private readonly ILogger _logger;
    7. public Worker(ILogger logger)
    8. {
    9. _logger = logger;
    10. }
    11. //重写BackgroundService.StartAsync方法,在开始服务的时候,执行一些处理逻辑,这里我们仅输出一条日志
    12. public override async Task StartAsync(CancellationToken cancellationToken)
    13. {
    14. _logger.LogInformation("Worker starting at: {time}", DateTimeOffset.Now);
    15. await base.StartAsync(cancellationToken);
    16. }
    17. ///
    18. /// 第一个 windows服务或linux守护程序 的处理逻辑,由RunTaskOne方法内部启动的Task任务线程进行处理,
    19. /// 同样可以从参数CancellationToken stoppingToken中的IsCancellationRequested属性,得知Worker Service服务是否已经被停止
    20. ///
    21. ///
    22. ///
    23. protected async Task RunTaskOne(CancellationToken stoppingToken)
    24. {
    25. var _crontab = Crontab.SecondlyAt(1, 10, 20); // 每秒
    26. 如果服务被停止,那么下面的IsCancellationRequested会返回true,我们就应该结束循环
    27. //while (!stoppingToken.IsCancellationRequested)
    28. //{
    29. // await Task.Delay(_crontab.GetSleepTimeSpan(DateTime.Now), stoppingToken);
    30. // _logger.LogInformation("RunTaskOne running at: {time}", DateTimeOffset.Now);
    31. // // Thread.Sleep(1000);
    32. //}
    33. //如果服务被停止,那么下面的IsCancellationRequested会返回true,我们就应该结束循环
    34. while (!stoppingToken.IsCancellationRequested)
    35. {
    36. await Task.Delay(_crontab.GetSleepTimeSpan(DateTime.Now), stoppingToken);
    37. await Task.Run(() =>
    38. {
    39. _logger.LogInformation("RunTaskOne running at: {time}", DateTimeOffset.Now);
    40. }, stoppingToken);
    41. }
    42. }
    43. ///
    44. /// 第二个 windows服务或linux守护程序 的处理逻辑,由RunTaskTwo方法内部启动的Task任务线程进行处理,
    45. /// 同样可以从参数CancellationToken stoppingToken中的IsCancellationRequested属性,得知Worker Service服务是否已经被停止
    46. ///
    47. ///
    48. ///
    49. protected async Task RunTaskTwo(CancellationToken stoppingToken)
    50. {
    51. var _crontab = Crontab.SecondlyAt(30, 35, 40); // / 每第 3,5,6 秒
    52. 如果服务被停止,那么下面的IsCancellationRequested会返回true,我们就应该结束循环
    53. //while (!stoppingToken.IsCancellationRequested)
    54. //{
    55. // await Task.Delay(_crontab.GetSleepTimeSpan(DateTime.Now), stoppingToken);
    56. // _logger.LogInformation("RunTaskTwo running at: {time}", DateTimeOffset.Now);
    57. // // Thread.Sleep(1000);
    58. //}
    59. //如果服务被停止,那么下面的IsCancellationRequested会返回true,我们就应该结束循环
    60. while (!stoppingToken.IsCancellationRequested)
    61. {
    62. await Task.Delay(_crontab.GetSleepTimeSpan(DateTime.Now), stoppingToken);
    63. await Task.Run(() =>
    64. {
    65. _logger.LogInformation("RunTaskTwo running at: {time}", DateTimeOffset.Now);
    66. }, stoppingToken);
    67. }
    68. }
    69. ///
    70. /// 第三个 windows服务或linux守护程序 的处理逻辑,由RunTaskThree方法内部启动的Task任务线程进行处理,
    71. /// 同样可以从参数CancellationToken stoppingToken中的IsCancellationRequested属性,得知Worker Service服务是否已经被停止
    72. ///
    73. ///
    74. ///
    75. protected async Task RunTaskThree(CancellationToken stoppingToken)
    76. {
    77. var _crontab = Crontab.SecondlyAt(45, 50, 55); // / 每第 3,5,6 秒
    78. 如果服务被停止,那么下面的IsCancellationRequested会返回true,我们就应该结束循环
    79. //while (!stoppingToken.IsCancellationRequested)
    80. //{
    81. // await Task.Delay(_crontab.GetSleepTimeSpan(DateTime.Now), stoppingToken);
    82. // _logger.LogInformation("RunTaskThree running at: {time}", DateTimeOffset.Now);
    83. // // Thread.Sleep(1000);
    84. //}
    85. //如果服务被停止,那么下面的IsCancellationRequested会返回true,我们就应该结束循环
    86. while (!stoppingToken.IsCancellationRequested)
    87. {
    88. await Task.Delay(_crontab.GetSleepTimeSpan(DateTime.Now), stoppingToken);
    89. await Task.Run(() =>
    90. {
    91. _logger.LogInformation("RunTaskThree running at: {time}", DateTimeOffset.Now);
    92. }, stoppingToken);
    93. }
    94. }
    95. protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    96. {
    97. //while (!stoppingToken.IsCancellationRequested)
    98. //{
    99. // _logger.LogInformation("Worker1 正在进行中 : {time}", DateTimeOffset.Now);
    100. // await Task.Delay(1000, stoppingToken);
    101. //}
    102. try
    103. {
    104. RunTaskOne(stoppingToken);
    105. RunTaskTwo(stoppingToken);
    106. RunTaskThree(stoppingToken);
    107. await Task.CompletedTask;
    108. // await Task.WhenAll(taskOne, taskTwo, taskThree);//使用await关键字,异步等待RunTaskOne、RunTaskTwo、RunTaskThree方法返回的三个Task对象完成,这样调用ExecuteAsync方法的线程会立即返回,不会卡在这里被阻塞
    109. }
    110. catch (Exception ex)
    111. {
    112. //RunTaskOne、RunTaskTwo、RunTaskThree方法中,异常捕获后的处理逻辑,这里我们仅输出一条日志
    113. _logger.LogError(ex.Message);
    114. }
    115. finally
    116. {
    117. //Worker Service服务停止后,如果有需要收尾的逻辑,可以写在这里
    118. }
    119. }
    120. //重写BackgroundService.StopAsync方法,在结束服务的时候,执行一些处理逻辑,这里我们仅输出一条日志
    121. public override async Task StopAsync(CancellationToken cancellationToken)
    122. {
    123. _logger.LogInformation("Worker1 停止了 : {time}", DateTimeOffset.Now);
    124. await base.StopAsync(cancellationToken);
    125. }
    126. }
    127. }

    其他方法可以参考:

    https://www.cnblogs.com/PatrickLiu/p/15834732.html

    25. 辅助角色服务 | Furion

    26.2 Cron 表达式 | Furion

  • 相关阅读:
    GEE学习总结(9)——像元二分法计算月度植被覆盖度(MODIS)
    WinRAR广告屏蔽办法
    Google浏览器插件推荐
    产业园区十大企业服务体系!
    深度剖析数据在内存中的存储
    关于良率:交期延误、报废补料、不做退款都是什么情况?
    golang中协程&管道&锁
    计算AUC的方法以及代码实现
    面试题c/c++--语言基础
    批量删除所有文件名称中的英文字母
  • 原文地址:https://blog.csdn.net/puzi0315/article/details/133502871