Longbow.Tasks 实战—任务持久化
<p>原文地址 https://www.cnblogs.com/ysmc/p/18795934</p><p> 之前写过一个文章,是介绍Longbow.Tasks这个定时任务调度库的,然后不少小伙伴问过我,怎么东西怎么用,也怪我,在那篇文章结尾我讲过要出实战的,后来抛之脑后了,实在惭愧。</p>
<p> 简单讲下这个库的情况,Longbow.Tasks 于Gitee 上开源,这个是开源地址:https://gitee.com/Longbow/Longbow.Tasks ,最主要的是改库支持 NETFramework 4.5+ 与 NETCore 2.0+。<br></p>
<p> 先来回顾一下怎么使用这个库:</p>
<h3>初始化</h3>
<p>.NET Core 中,包括 .NET 5 .NET 6 .NET 7.....需要注入服务</p>
<div class="cnblogs_code">
<pre>builder.Services.AddTaskServices();</pre>
</div>
<p>NETFramework 4.5+</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 程序入口调用</span>
TaskServicesManager.Init();</pre>
</div>
<h3>使用例子</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">立即执行,仅执行一次</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> TaskServicesManager.GetOrAdd<TasksDemo>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">任务唯一标识</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">周期性任务 (1 分钟后间隔 5 秒执行2次任务)</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">var</span> trigger = TriggerBuilder.Default.WithInterval(TimeSpan.FromSeconds(<span style="color: rgba(128, 0, 128, 1)">5</span>)).WithRepeatCount(<span style="color: rgba(128, 0, 128, 1)">2</span>).WithStartTime(DateTimeOffset.Now.AddMinutes(<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">)).Build();
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span> TaskServicesManager.GetOrAdd<TasksDemo>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">任务唯一标识</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, trigger);
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">支持cron表达式,间隔 5 秒循环执行任务</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> TaskServicesManager.GetOrAdd<TasksDemo>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">任务唯一标识</span><span style="color: rgba(128, 0, 0, 1)">"</span>, TriggerBuilder.Build(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*/5 * * * * *</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 128, 1)">11</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里重点关注,可以让你的任务接收 serviceProvider 参数,这样就可以使用注入的服务了</span>
<span style="color: rgba(0, 128, 128, 1)">13</span> TaskServicesManager.GetOrAdd(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">任务唯一标识</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">async</span> (serviceProvider, token) =>
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">15</span> System.Console.WriteLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">任务唯一标识</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">await</span> Task.Delay(<span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">17</span> }, TriggerBuilder.Build(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*/5 12 * * * *</span><span style="color: rgba(128, 0, 0, 1)">"</span>));</pre>
</div>
<h3>持久化</h3>
<p> 这里我使用 .NET 8 为例子,主要使用的是 依赖项注入-键控服务</p>
<p>1、我们先定义一个任务接口</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> ITestService
{
Task Run(IServiceProvider serviceProvider);
}</span></pre>
</div>
<p>2、注册几个任务</p>
<div class="cnblogs_code">
<p>builder.Services.AddKeyedTransient<ITestService, Test1Service>("Test1");<br>builder.Services.AddKeyedTransient<ITestService, Test2Service>("Test2");<br>builder.Services.AddKeyedTransient<ITestService, Test3Service>("Test3");</p>
</div>
<p>3、写一个 IHostedService,用于定时任务的添加</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestHostedService : IHostedService
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span><span style="color: rgba(0, 0, 0, 1)"> IServiceProvider _serviceProvider;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> TestHostedService(IServiceProvider serviceProvider)
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> _serviceProvider =<span style="color: rgba(0, 0, 0, 1)"> serviceProvider;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 假设这里是从数据库中读取的定时任务
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">public</span> Dictionary<<span style="color: rgba(0, 0, 255, 1)">string</span>, <span style="color: rgba(0, 0, 255, 1)">string</span>> Servers = <span style="color: rgba(0, 0, 255, 1)">new</span> Dictionary<<span style="color: rgba(0, 0, 255, 1)">string</span>, <span style="color: rgba(0, 0, 255, 1)">string</span>><span style="color: rgba(0, 0, 0, 1)">()
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">key为服务名称,value为cron表达式</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Task1</span><span style="color: rgba(128, 0, 0, 1)">"</span>] = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*/5 12 * * * *</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">17</span> [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Task2</span><span style="color: rgba(128, 0, 0, 1)">"</span>] = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*/10 12 * * * *</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">18</span> [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Task3</span><span style="color: rgba(128, 0, 0, 1)">"</span>] = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*/15 12 * * * *</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)">20</span>
<span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span><span style="color: rgba(0, 0, 0, 1)"> Task StartAsync(CancellationToken cancellationToken)
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 255, 1)">await</span> <span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">var</span> scope =<span style="color: rgba(0, 0, 0, 1)"> _serviceProvider.CreateAsyncScope();
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> server <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> Servers)
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据服务名称获取服务</span>
<span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 255, 1)">var</span> testServices = scope.ServiceProvider.GetKeyedServices<ITestService><span style="color: rgba(0, 0, 0, 1)">(server.Key);
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (testServices.Any())
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)">正常来说一个任务对应一个服务,这里只取第一个</span>
<span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 255, 1)">var</span> testService =<span style="color: rgba(0, 0, 0, 1)"> testServices.First();
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 添加定时任务</span>
<span style="color: rgba(0, 128, 128, 1)">33</span> TaskServicesManager.GetOrAdd(server.Key, <span style="color: rgba(0, 0, 255, 1)">async</span> (serviceProvider, token) =>
<span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> testService.Run(serviceProvider);
</span><span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 0, 1)"> }, TriggerBuilder.Build(server.Value));
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">38</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">40</span>
<span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Task StopAsync(CancellationToken cancellationToken)
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">43</span> Console.WriteLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">StopAsync</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">44</span>
<span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
</span><span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">47</span> }</pre>
</div>
<p> 代码就这么多,感谢各位大佬的观看!</p>
</div>
<div id="MySignature" role="contentinfo">
<p>本文来自博客园,作者:一事冇诚,转载请注明原文链接:https://www.cnblogs.com/ysmc/p/18795934</p><br><br>
来源:https://www.cnblogs.com/ysmc/p/18795934
頁:
[1]