开源地址
https://github.com/1448376744/Quartz
由于quartz.net对容器支持不够友好,而且配置复杂,看不懂,还不支持过滤器,只能自己动手写一个
基本使用,每次执行任务时都会从容器解析一个新的任务实例以及依赖
static async Task Main(string[] args) { //创建容器 var services = new ServiceCollection(); services.AddScoped<Logger>(); services.AddQuartzFactory(b => { //设置时区 b.PerExecuteUtcTime = () => DateTime.UtcNow.AddHours(8); //添加任务 b.AddTask<MyQuartzTask>("0/1 * * * * ?", typeof(MyQuartzTaskFilter), typeof(MyQuartzTaskFilter2)); }); //构建容器 var provider = services.BuildServiceProvider(); //从容器获取任务调度工厂 var factory = provider.GetRequiredService<QuartzFactory>(); //启动任务调度 await factory.StartAsync(); }
定义一个任务
public class MyQuartzTask : IQuartzTask { readonly Logger _logger = null; public MyQuartzTask(Logger logger) { _logger = logger; } public async Task ExecuteAsync(TaskExecutingContext context) { await Task.Run(() => { Console.ForegroundColor = ConsoleColor.Green; _logger.Log($"[任务:1][时间:{DateTime.Now}][线程ID:{Thread.CurrentThread.ManagedThreadId}],执行目标任务"); Console.ForegroundColor = ConsoleColor.White; }); } }
定义过滤器1
public class MyQuartzTaskFilter : IQuartzTaskFilter { public async Task OnExecuteAsync(TaskExecutingContext context, QuartzTaskExecuteDelegate next) { Console.WriteLine("[过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务"); await next(); Console.WriteLine("[过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务"); } }
定义过滤器2
public class MyQuartzTaskFilter2 : IQuartzTaskFilter { public async Task OnExecuteAsync(TaskExecutingContext context, QuartzTaskExecuteDelegate next) { Console.WriteLine("[过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务"); await next(); Console.WriteLine("[过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务"); } }
定义一个日志,用于测试依赖注入,支持scope级别
public class Logger { public void Log(string message) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(message); Console.ForegroundColor = ConsoleColor.White; } }
跑起来,从执行结果虽然看不出是1秒一次,底层是基于线程池的任务排队进行的,由于控制台打印的延迟,导致Datetime.Now获得的时间不一定是一秒一次
[过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务 [过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务 [任务:1][时间:2020/4/4 14:15:05][线程ID:6],执行目标任务 [过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务 [过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务 [过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务 [过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务 [任务:1][时间:2020/4/4 14:15:06][线程ID:5],执行目标任务 [过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务 [过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务 [过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务 [过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 开启事务 [任务:1][时间:2020/4/4 14:15:08][线程ID:6],执行目标任务 [过滤器2][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务 [过滤器1][线程ID:{Thread.CurrentThread.ManagedThreadId}] 关闭事务
过滤器栈源码实现
创建一个过滤器执行器,实现原理是递归
/// <summary> /// 过滤器执行器 /// </summary> public class QuartzFilterExecutor { /// <summary> /// 过滤器 /// </summary> private Queue<IQuartzTaskFilter> _filters = new Queue<IQuartzTaskFilter>(); /// <summary> /// 创建一个过滤器执行器 /// </summary> /// <param name="filters"></param> public QuartzFilterExecutor(List<IQuartzTaskFilter> filters) { foreach (var item in filters) { _filters.Enqueue(item); } } /// <summary> /// 执行过滤器栈 /// </summary> /// <param name="next">任务执行器</param> /// <returns></returns> public Task Execute(Func<Task> next) { return Builder(next)(); } /// <summary> /// 构建执行器栈,递归 /// </summary> /// <param name="next">任务执行器</param> /// <returns></returns> private Func<Task> Builder(Func<Task> next) { if (_filters.Count > 0) { var filter = _filters.Dequeue(); async Task current() { await filter.OnExecuteAsync(new TaskExecutingContext { }, new QuartzTaskExecuteDelegate(Builder(next))); } return current; } else { return next; } } }
过滤器接口
/// <summary> /// 过滤器 /// </summary> public interface IQuartzTaskFilter { /// <summary> /// 任务执行过滤 /// </summary> /// <param name="context">任务执行上下文</param> /// <param name="next">任务委托</param> /// <returns></returns> Task OnExecuteAsync(TaskExecutingContext context, QuartzTaskExecuteDelegate next); } /// <summary> /// 任务执行委托 /// </summary> /// <returns></returns> public delegate Task QuartzTaskExecuteDelegate();
任务接口
/// <summary> /// 任务 /// </summary> public interface IQuartzTask { Task ExecuteAsync(TaskExecutingContext context); }
跑起来
static async Task Main(string[] args) { //创建任务级过滤器 var task = new MyQuartzTask(new Logger()); var filter1 = new MyQuartzTaskFilter(); var filter2 = new MyQuartzTaskFilter(); var executor = new QuartzFilterExecutor(new IQuartzTaskFilter[] { filter1,filter2 }.ToList()); //执行任务及过滤器栈 await executor.Execute(()=>task.ExecuteAsync(new TaskExecutingContext { })); }
有建议和不正之处欢迎指出,多多学习!