Quartz.NET 3.0

Quartz.NET是一个强大、开源、轻量的作业调度框架,你能够用它来为执行一个作业而创建简单的或复杂的作业调度。Quartz.NET 3.0支持了.NET Core 和async/await。

官网:http://www.quartz-scheduler.net/

源码:https://github.com/quartznet/quartznet

示例:https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html

废话不多说直接上代码

nuget引用Quartz 3.0

  1. 用代码调度定时任务
        public async static Task Init()
        {
            LogProvider.SetCurrentLogProvider(new CustomConsoleLogProvider());//Quartz提供了日志接口,这里可以自定义日志
            #region Scheduler 调度器
            StdSchedulerFactory factory = new StdSchedulerFactory();
            IScheduler scheduler = await factory.GetScheduler();//获取调度器
            scheduler.ListenerManager.AddSchedulerListener(new CustomSchedulerListener());//添加调度器监听
            scheduler.ListenerManager.AddTriggerListener(new CustomTriggerListener());//添加时间策略监听
            scheduler.ListenerManager.AddJobListener(new CustomJobListener());//添加作业监听
            await scheduler.Start();//启动调度器
            #endregion

            #region 创建Job(作业)
            IJobDetail jobDetail = JobBuilder.Create<TestJob>()
                    .WithIdentity("testjob", "group1")//testjob- 作业名称  group1-分组名称
                    .WithDescription("This is TestJob jobDetail")//添加描述
                    .Build();

            jobDetail.JobDataMap.Add("key1", "value1");
            jobDetail.JobDataMap.Add("key2", "value2");
            jobDetail.JobDataMap.Add("key3", "value3");
            #endregion

            # region 创建时间策略 ITrigger
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("testtrigger1", "group1")//testtrigger1- 时间策略名称  group1-分组名称
                .StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(10)))//10秒后启动
                //.StartNow() //马上启动
                .WithCronSchedule("5/10 * * * * ?")//每隔10秒执行一次
                .WithDescription("This is testjob's Trigger")//添加描述
                .Build();
            #endregion

            await scheduler.ScheduleJob(jobDetail,trigger);//按时间策略调度作业
        }
    public class CustomConsoleLogProvider : ILogProvider
    {
        public Logger GetLogger(string name)
        {
            return new Logger((level, func, exception, parameters) =>
            {
                if (level >= LogLevel.Info && func != null)
                {
                    Console.WriteLine($"[{ DateTime.Now.ToLongTimeString()}] [{ level}] { func()} {string.Join(";", parameters.Select(p => p == null ? " " : p.ToString()))}  自定义日志{name}");
                }
                return true;
            });
        }

        public IDisposable OpenMappedContext(string key, string value)
        {
            throw new NotImplementedException();
        }

        public IDisposable OpenNestedContext(string message)
        {
            throw new NotImplementedException();
        }
    }

    public class CustomSchedulerListener : ISchedulerListener
    {
        public async Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($" {DateTime.Now} {nameof(JobAdded)} {Thread.CurrentThread.ManagedThreadId} {jobDetail.Description}");
            });
        }

        public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public async Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($" {DateTime.Now} {nameof(JobScheduled)} {Thread.CurrentThread.ManagedThreadId} {trigger.Description}");
            });
        }

        public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerShutdown(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task SchedulerShuttingdown(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public async Task SchedulerStarted(CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($" {DateTime.Now} {nameof(SchedulerStarted)} {Thread.CurrentThread.ManagedThreadId} {cancellationToken.WaitHandle.SafeWaitHandle.GetHashCode()}");
            });
        }

        public async Task SchedulerStarting(CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($" {DateTime.Now} {nameof(SchedulerStarting)} {Thread.CurrentThread.ManagedThreadId} {cancellationToken.WaitHandle.SafeWaitHandle.GetHashCode()}");
            });
        }

        public Task SchedulingDataCleared(CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }
    }

    public class CustomJobListener : IJobListener
    {
        public string Name => nameof(CustomJobListener);

        public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
        {
            await Task.Run(() => {
                Console.WriteLine($"CustomJobListener JobExecutionVetoed {context.JobDetail.Description}");
            });
        }

        public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
        {
            await Task.Run(() => {
                Console.WriteLine($"CustomJobListener JobToBeExecuted {context.JobDetail.Description}");
            });
        }

        public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken))
        {
            await Task.Run(() => {
                Console.WriteLine($"CustomJobListener JobWasExecuted {context.JobDetail.Description}");
            });
        }
    }

    public class CustomTriggerListener : ITriggerListener
    {
        public string Name =>nameof(CustomTriggerListener);

        public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener TriggerComplete {trigger.Description}");
            });
        }

        public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener TriggerFired {trigger.Description}");
            });
        }

        public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
            });
        }

        public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default)
        {
            await Task.Run(() =>
            {
                Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
            });
            return false;//false才能继续执行
        }
    }

    public class TestJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            await Task.Run(() =>
            {
                //需要执行的方法
                Console.WriteLine($"{nameof(TestJob)} {Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
            });
        }
    }

  1. 结合Topshelf配置文件调度定时任务
            HostFactory.Run(x =>
            {
                x.Service<ServiceRunner>();
                x.EnablePauseAndContinue();
            });

    public sealed class ServiceRunner : ServiceControl, ServiceSuspend
    {
        private readonly IScheduler scheduler;

        public ServiceRunner()
        {
            scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
            scheduler.ListenerManager.AddSchedulerListener(new CustomSchedulerListener());//添加调度器监听
        }

        public bool Start(HostControl hostControl)
        {
            scheduler.Start();
            return true;
        }

        public bool Stop(HostControl hostControl)
        {
            scheduler.Shutdown(false);
            return true;
        }

        public bool Continue(HostControl hostControl)
        {
            scheduler.ResumeAll();
            return true;
        }

        public bool Pause(HostControl hostControl)
        {
            scheduler.PauseAll();
            return true;
        }
    }

quartz.config

# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedence

quartz.scheduler.instanceName = QuartzTest

# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal

# job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml

# export this server to remoting context
#quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
#quartz.scheduler.exporter.port = 555
#quartz.scheduler.exporter.bindName = QuartzScheduler
#quartz.scheduler.exporter.channelType = tcp
#quartz.scheduler.exporter.channelName = httpQuartz

# 添加Job(作业)监听
quartz.jobListener.CustomJobListener.type=TestConsole.QuartzHelper.CustomJobListener,TestConsole
# 添加Trigger(时间策略)监听
quartz.triggerListener.CustomTriggerListener.type=TestConsole.QuartzHelper.CustomTriggerListener,TestConsole

quartz_jobs.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- This file contains job definitions in schema version 2.0 format -->

<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">

  <processing-directives>
    <overwrite-existing-data>true</overwrite-existing-data>
  </processing-directives>
  <schedule> 
    <job>
      <name>TestJob</name>
      <group>TestJob</group>
      <description>TestJob</description>
      <job-type>TestConsole.QuartzHelper.TestJob,TestConsole</job-type>
      <durable>true</durable>
      <recover>false</recover>
    </job>
    <trigger>
      <cron>
        <name>TestJobTrigger</name>
        <group>TestJob</group>
        <job-name>TestJob</job-name>
        <job-group>TestJob</job-group>
        <start-time>2017-01-25T00:00:00+08:00</start-time>
        <cron-expression>0/10 * * * * ? </cron-expression>
      </cron>
    </trigger>

  </schedule>
</job-scheduling-data>

使用配置文件需要注意的是nuget需要引入Quartz.Plugins

本文参考文档:
posted @ 2020-05-19 17:36  德乌姆列特  阅读(728)  评论(0编辑  收藏  举报