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

本文參考文檔:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM