Asynchronous Scheduler for Quartz3.0 Timed Task Learning

Posted by bhavin12300 on Thu, 21 May 2020 05:00:03 +0200

Preface

There are two main differences between Quartz3 and Quartz2:

1. Quartz3 takes its resource class library apart in more detail. For example, if you want to use Quartz3 for development, you should at least reference Quartz.Quartz.Jobs,Quartz.Plugins These three class libraries.

2. Quartz3 as a whole uses asynchronous instance creation, so we have to use async, await syntax.

Let's do a task scheduling with Quartz3.

Create Scheduler Management Class

First create the Jops class library, then search in Nuget Quartz.Plugins; as follows:

becauseQuartz.PluginsDependent on Quartz, so introducedQuartz.PluginsQuartz is automatically introduced.

Then we create a task scheduling management class, ScheduleControler.The code is as follows:

public class ScheduleControler
​
{
    private static IScheduler scheduler;
    private static Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>> dicJop = new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>>();
    
    private static int triggerId = 0;
    private static string defaultGroupName = "Default Group";
    /// <summary>
    ///Initialize Scheduler
    /// </summary>
    /// <returns></returns>
    public static async Task Init()
    {
        try
        {
            //Quartz.configKey-value pairs in profile
            //NameValueCollection props = new NameValueCollection
            //{
            //   { "quartz.serializer.type", "binary" }
            //};
            StdSchedulerFactory factory = new StdSchedulerFactory(); 
            scheduler = await factory.GetScheduler(); 
            await scheduler.Start(); 
        }
        catch (SchedulerException se)
        {
            System.Console.WriteLine(se);
        }
    }
    /// <summary>
    ///Run Scheduler Task
    /// </summary>
    /// <returns></returns>
    public static async Task Run()
    {
        try
        {
            await scheduler.ScheduleJobs(dicJop, true);
​
        }
        catch (SchedulerException se)
        {
            System.Console.WriteLine(se);
        }
    }
    /// <summary>
    ///Close Scheduler
    /// </summary>
    /// <returns></returns>
    public static async Task Shutdown()
    {
        try
        { 
            await scheduler.Shutdown(); 
​
        }
        catch (SchedulerException se)
        {
            System.Console.WriteLine(se);
        }
    }
    /// <summary>
    ///Add Tasks
    /// </summary>
    /// <typeparam name="T">task type, inherit Ijop</typeparam>
    /// <param name="jopName">task name</param>
    /// <param name="Interval">Run interval/sec**Minimum 1 second</param>
    /// <param name="period">wait for startup time/sec**-1 for immediate startup </param>
    /// <param name="repeatTime">Number of repeats**-1 Runs forever</param>
    /// <param name="endAt">End/sec after specified time**0 is no end time specified, default value is 0</param>
    public static void PushJop<T>(string jopName, int Interval, int period=-1,int repeatTime=-1,int endAt=0)  where T:IJob
        {
            try
            {
                if (Interval <= 0)
                {
                    Interval = 1;
                }
                if (period < -1)
                {
                    period = -1;
                }
                if (repeatTime < -1)
                {
                    repeatTime = -1;
                } 
                if (endAt < 0)
                {
                    endAt = -1;
                }
                IJobDetail job = JobBuilder.Create<T>().WithIdentity(jopName, defaultGroupName).UsingJobData("Name", "IJobDetail").Build();
            
                var triggerBuilder  = TriggerBuilder.Create().WithIdentity($"{jopName}.trigger{triggerId}", defaultGroupName);
                if (period == -1)
                {
                    triggerBuilder = triggerBuilder.StartNow();
                }
                else
                {
                    DateTimeOffset dateTimeOffset = DateTimeOffset.Now.AddSeconds(period);
                    triggerBuilder = triggerBuilder.StartAt(dateTimeOffset);
                }
                if (endAt > 0)
                {
                    triggerBuilder = triggerBuilder.EndAt(new DateTimeOffset(DateTime.Now.AddSeconds(endAt)));
                }  
​
                if (repeatTime == -1)
                {
                    triggerBuilder = triggerBuilder.WithSimpleSchedule(x => x.WithIntervalInSeconds(Interval).RepeatForever());  
                }
                else
                {
                    triggerBuilder = triggerBuilder.WithSimpleSchedule(x => x.WithRepeatCount(Interval).WithRepeatCount(repeatTime));
                }
                ITrigger trigger = triggerBuilder.UsingJobData("Name", "ITrigger")
                     .WithPriority(triggerId)//Set trigger priority, the highest priority [the highest number] when multiple triggers start at the same time
                     .Build(); 
​
                dicJop.Add(job, new HashSet<ITrigger>() { trigger }); 
                triggerId++; 
            }
            catch (SchedulerException se)
            {
                System.Console.WriteLine(se);
            }
        }
​
    public static void PushJop<T>(string jopName, string cronExpress) where T : IJob
    {
        try
        { 
            IJobDetail job = JobBuilder.Create<T>().WithIdentity(jopName, defaultGroupName).UsingJobData("Name", "IJobDetail").Build(); 
            ITrigger trigger = TriggerBuilder.Create()
               .WithIdentity($"{jopName}.trigger{triggerId}", defaultGroupName)
               .WithCronSchedule(cronExpress)
               .ForJob(job)
               .Build(); 
            dicJop.Add(job, new HashSet<ITrigger>() { trigger });
            triggerId++;
        }
        catch (SchedulerException se)
        {
            System.Console.WriteLine(se);
        }
    } 
}

You can see that the dispatcher management class contains four main functions, as follows:

Run Scheduler Task

Initialize Scheduler (Init)

Shutdown Scheduler

Add Task (PushJop)

Applications can use Quartz by calling these four functions.

Add Profile

quartz.config

Quartz.configThis is the configuration file for the dispatcher factory StdSchedulerFactory, which we can configure when initializing the dispatcher, but it is obviously easier to modify the settings in the configuration file.

Quartz.configThe contents are as follows:

# 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
#Specify quartz_Jobs.xmlRoute
#quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
​
# export this server to remoting context to release the following comment using CrystalQuartz
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

If configured at initialization, refer to the following code:

NameValueCollection props = new NameValueCollection
{
   { "quartz.serializer.type", "binary" }
};
StdSchedulerFactory factory = new StdSchedulerFactory(props); 

quartz_jobs.xml

Quartz_Jobs.xmlIs a task profile used to configure tasks.However, the task is configured with the PushJop function passed by the scheduler management class in this article, so quartz_is not requiredJobs.xmlIt's configured in the file, but for testing purposes, we'll add a quartz_Jobs.xmlFile becauseQuartz.configThe file specifies that quartz_is configuredJobs.xmlSo it would be abnormal without it.

Here we add an empty quartz_Jobs.xmlFile as follows:

<?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> 
  </schedule>
</job-scheduling-data>

Create Task

Create a task class (Jop) to handle business operations. The task class inherits the IJop interface with the following code.

 public class HelloJob : IJob
 {
     public async Task Execute(IJobExecutionContext context)
     {
         Task task = new Task(() => {
             LogicMethod(context);
         });
         task.Start();
         await task;
     }
     public void LogicMethod(IJobExecutionContext context)
     {
         Console.Out.WriteLine($"HelloJob DateTime:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}  Key:{context.JobDetail.Key} ");
     } 
 } 

Test Quartz

Create a new console project, QuartzNetTest, which introduces the Jops class library and Quartz.Plugins.

Then modify the Main function to configure the HelloJob task to run every three seconds as follows:

static void Main(string[] args)
{
    ScheduleControler.Init().GetAwaiter().GetResult();
    ScheduleControler.PushJop<HelloJob>("HelloWord", 3);
    ScheduleControler.Run().GetAwaiter().GetResult();
    var info = Console.ReadKey();
    if (info.Key == ConsoleKey.Enter)
    {
        ScheduleControler.Shutdown().GetAwaiter().GetResult();
        Console.WriteLine("End");
    }
    Console.Read();
}

Run the project as follows:

Quartz ran successfully.

Quartz Task Manager

In addition to running tasks on a regular basis, QuartzNet also provides a task manager.Next, let's create a new Quartz task management.

Create an empty Web project, QuartzNetWebManager.

Add Dependent Class Library

Nuget Search CrystalQuartz.Remote Install.

Search for Quartz installations again and note that the Quartz installed here is not Quartz.Plugins.

This completes Quartz's task management.

Then when we open WebConfig, we can see that there is an additional crystalQuartz node under configuration, an additional handlers under webServer, read the configuration file, and find that Quartz's Task Manager specifies a web page CrystalQuartzPanel.axd For access address,.

WebConfig is as follows:

<crystalQuartz>
    <provider>
      <add property="Type" value="CrystalQuartz.Core.SchedulerProviders.RemoteSchedulerProvider, CrystalQuartz.Core" />
      <!-- Edit scheduler host value below =================================== -->
      <add property="SchedulerHost" value="tcp://localhost:555/QuartzScheduler" />
      <!--                                 =================================== -->
    </provider>
</crystalQuartz>
<system.webServer>
    <handlers>
      <add name="CrystalQuartzPanel" verb="*" path="CrystalQuartzPanel.axd" type="CrystalQuartz.Web.PagesHandler, CrystalQuartz.Web" />
    </handlers>
  </system.webServer>

Visit Web Site https://localhost:44302/CrystalQuartzPanel.axd , the management interface is as follows:

You can see that in addition to displaying the currently running tasks, Manager also provides functions such as deleting tasks, executing them immediately, and so on; it is very convenient.

Of course, Quartz has many more features, so we can go to the official website to learn.

QuartzNet: https://www.quartz-scheduler.net/

----------------------------------------------------------------------------------------------------

The code has already been uploaded to Github. You are welcome to download it.

Github address: https://github.com/kiba518/QuartzTest

----------------------------------------------------------------------------------------------------

Note: This article is original. Please contact the author for authorization and indicate the source of any form of reprinting!
If you find this article good, please click on the Recommendation below. Thank you very much!

https://www.cnblogs.com/kiba/p/12794928.html

 

Topics: C# xml github encoding