定时调度插件------Longbow.Tasks

官网地址Longbow.Tasks

使用说明

dll引用

  • 使用NuGet 搜索Longbow.Task可找到相关版本的dll

    目前最新的为7.0.0版本,需net6.0+

    如果低版本用户可使用5.2.1

  • 直接下载源码编译即可

dll引入程序

  • .netcore 容器注入
services.AddTaskServices();
  • donet4.5+ 使用
// 程序入口调用
TaskServicesManager.Init();

自定义业务实现(Job)

  • 自定义业务类

    /// <summary>
    /// 后台任务实现类
    /// </summary>
    public class FooTask : ITask
    {
        /// <summary>
        /// 后台任务具体业务操作
        /// </summary>
        public async Task Execute(CancellationToken cancellationToken)
        {
            // 模拟任务执行耗时500毫秒
            try
            {
                await Task.Delay(500, cancellationToken);
            }
            catch (TaskCanceledException) { }
            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }
            // do something ...
        }
    }
    
  • 将自定义业务类添加到程序中

    // 1.将FooTask添加,默认使用内部的触发器
    TaskServicesManager.GetOrAdd<FooTask>().Task.Execute(default);
    // 2.设置触发器Cron
    // 每分钟的第 5 秒循环执行任务
    TaskServicesManager.GetOrAdd<FooTask>("表达式任务", token => Task.Delay(1000), TriggerBuilder.Build("5 * * * * *"));
    

测例代码说明

CronTest测例

  • DateTimeOffset 与DateTime的不同:多存储了时区

  • 通过Cron类来获得下次执行的时间

    var now = DateTimeOffset.Now;
    // 1.当前时间加5s与后者相等
    // Cron.Secondly():返回Cron的string
    // ParseCronExpression(): 将string转换为CronExpression
    // GetNextExecution:通过参数的时间来获得下次执行的时间
     Assert.Equal(now.AddSeconds(5), Cron.Secondly(5).ParseCronExpression().GetNextExecution(now));
    // 2.每 2 秒 执行一次
    var cron = "*/2 * * * * *".ParseCronExpression();
    // 获取一个一分钟之内的任务列表
    var nextRuntimes = cron.GetOccurrences(now, now.AddMinutes(1), TimeZoneInfo.Local).Take(3).ToList();
    // 每个任务间隔时间为2s
    Assert.Equal(nextRuntimes[0].AddSeconds(2), nextRuntimes[1]);
    Assert.Equal(nextRuntimes[1].AddSeconds(2), nextRuntimes[2]);
    // 3.cron必须按照时间规格来设置,不能超过
    

DictionaryTest测例

// ConcurrentDictionary进行AddOrUpdate时,如果内部使用了并发代码,需要使用懒加载模式
 var tasks = Enumerable.Range(1, 5).Select(i => Task.Run(() =>
 {
	var temp = pool.AddOrUpdate("Test", key => new Lazy<string>(() =>
     {
     	var t = GenerateValue(i); //返回的为Task<string>
     	t.Wait();
     	return t.Result;
     }), (key, value) => new Lazy<string>(() =>
     {
     	var t = UpdateValue(i); //返回的为Task<string>
     	t.Wait();
    	return t.Result;
     }));
 }));

ScheduleTaskTest测例

// 1.CancellationTokenSource的WaitOne方法
var cts = new CancellationTokenSource();
// 返回false表示2s已经过去,任务未结束
Assert.False(cts.Token.WaitHandle.WaitOne(2000));
// 1s后结束任务
cts.CancelAfter(1000);
// 返回true,表示2s内任务已经结束
Assert.True(cts.Token.WaitHandle.WaitOne(2000));
// 2.TriggerBuilder触发器
// 每秒执行一次,无超时时间,从当前时间开始,第三个参数可为空,表示当前时间
TriggerBuilder.Build(Cron.Secondly(), -1, DateTimeOffset.Now);
// 创建当前时间的触发器
TriggerBuilder.Default.WithStartTime().Build();
// 以1000毫秒为周期的触发器
TriggerBuilder.Default.WithInterval(1000).Build();
// 设置超时时间为1s,第二个参数不设置则为Timeout.InfiniteTimeSpan
 TriggerBuilder.Build(Cron.Secondly(), 1000);

TaskManagerTest测例

// 1.开始任务
// Foo2Task重载ExecutableTask方法并实现ConfigureStartInfo接口
// Command和Argumens为命令行的相关参数
var sche = TaskServicesManager.GetOrAdd<Foo2Task>();
await Task.Delay(300);
// 执行
await sche.Task.Execute(default);
// 2.触发器执行后的回调函数
sche.Triggers.First().PulseCallback = t =>{};

TaskStorageTest测例

// 1.当持久化以后,再次GetOrAdd时任务体不会被执行
TaskServicesManager.GetOrAdd("StorageRunOnce", token =>
{
    return Task.CompletedTask;
});

// 2.利用发射获得 IStorage 实例
var factory = typeof(TaskServicesManager).GetProperty("Factory", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
var instance = factory.GetValue(null, null);
var storageInstance = instance.GetType().GetProperty("Storage").GetValue(instance);
var option = storageInstance.GetType().GetProperty("Options").GetValue(storageInstance) as FileStorageOptions;
option.DeleteFileByRemoveEvent = true;
TaskServicesManager.Clear();
option.DeleteFileByRemoveEvent = false;

相关文档

Wiki: 传送门

posted @ 2023-01-03 11:02  摧残一生  阅读(343)  评论(0编辑  收藏  举报