完全基于net core容器的超级轻量化的Quartz,支持类似net core mvc的过滤器,附过滤器实现源码

开源地址

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 
     {
         
     }));
 }

有建议和不正之处欢迎指出,多多学习!

猜你喜欢

转载自www.cnblogs.com/chaeyeon/p/12631697.html