Using Quartz.Net in. Net Core Net

1, Introduction

  Quartz.Net is C# rewritten from Java's quartz. The latest version is 3.0.6. The source code is in https://github.com/quartznet/quartznet . The main function is to do some periodic work or regular work. For example, the data of the previous day are counted at 2 a.m. every day.

2, Simple case

Taking WebApi project as an example, use VS scaffold function to create a new WebApi project.

public void ConfigureServices(IServiceCollection services)
{
     services.AddMvc();
     services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();//Register an instance of ISchedulerFactory.
 }
   [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly ISchedulerFactory _schedulerFactory;
        private IScheduler _scheduler;
        public ValuesController(ISchedulerFactory schedulerFactory)
        {
            this._schedulerFactory = schedulerFactory;
        }
        [HttpGet]
        public async Task<string[]> Get()
        {       //1. Obtain the scheduler through the scheduling factory
            _scheduler = await _schedulerFactory.GetScheduler();       //2. Start scheduler
            await _scheduler.Start();
       //3. Create a trigger
            var trigger = TriggerBuilder.Create()
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).RepeatForever())//Every two seconds
                            .Build();
        //4. Create task
            var jobDetail = JobBuilder.Create<MyJob>()
                            .WithIdentity("job", "group")
                            .Build();
       //5. Bind triggers and taskers to the scheduler
            await _scheduler.ScheduleJob(jobDetail, trigger);
            return await Task.FromResult(new string[] { "value1", "value2" });
        }   }
public class MyJob : IJob//Create the implementation class of IJob and implement the execute method.
    {
        public Task Execute(IJobExecutionContext context)
        {      return Task.Run(() =>
              {                  using (StreamWriter sw = new StreamWriter(@"C:\Users\Administrator\Desktop\error.log", true, Encoding.UTF8))
                  {
                      sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                  }
            });
        }
    }

Output results:

2018-08-03 00-03-19
2018-08-03 00-03-20
2018-08-03 00-03-22
2018-08-03 00-03-24
2018-08-03 00-03-26

The Job executed above has no parameters. When parameters are required, parameters can be passed through the following two methods:

1. Add parameter value in Trigger

 var trigger3 = TriggerBuilder.Create()
                        .WithSimpleSchedule(x =>x.WithIntervalInSeconds(2).RepeatForever())//Always execute every 2 seconds
                        .UsingJobData("key1", 321)  //By adding parameter values in Trigger
                        .UsingJobData("key2", "123")
                        .WithIdentity("trigger2", "group1")
                        .Build();

2. Add parameter value in Job

 IJobDetail job = JobBuilder.Create<MyJob>()
                                .UsingJobData("key1", 123)//Adding parameter values through Job
                                .UsingJobData("key2", "123")
                                .WithIdentity("job1", "group1")
                                .Build();

Get the parameter value in the Job by the following method

public class MyJob : IJob
    {
        public Task Execute(IJobExecutionContext context)
        {
            var jobData = context.JobDetail.JobDataMap;//Get parameters in Job

            var triggerData = context.Trigger.JobDataMap;//Get parameters in Trigger

            var data = context.MergedJobDataMap;//Get the merged parameters in Job and Trigger

            var value1= jobData.GetInt("key1");
            var value2= jobData.GetString("key2");

            var dateString = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");return Task.Run(() =>
            {
                using (StreamWriter sw = new StreamWriter(@"C:\Users\Administrator\Desktop\error.log", true, Encoding.UTF8))
                {
                    sw.WriteLine(dateString);
                }
            });
        }
    }

When the parameter name in Job is the same as that in Trigger, use context When mergedjobdatamap gets the parameter, the value in Trigger will overwrite the value in Job.

3. The above situation can only adapt to the situation where the parameter value remains unchanged. In this case, if the parameter value this time is the value calculated after the last execution, the above method cannot be used. If the accumulation operation is implemented every two seconds, now the initial value is 0. If you follow the above operation to obtain the value, it will always be 0 + 1, and the return value will always be 1. To meet this situation, you only need to add a feature [PersistJobDataAfterExecution].

    [PersistJobDataAfterExecution]//Update the stored copy of JobDataMap of JobDetail so that the next execution of this task will receive the updated value instead of the original stored value
    public class MyJob : IJob
    {
        public Task Execute(IJobExecutionContext context)
        {
            var jobData = context.JobDetail.JobDataMap;
            var triggerData = context.Trigger.JobDataMap;
            var data = context.MergedJobDataMap;

            var value1 = jobData.GetInt("key1");
            var value2 = jobData.GetString("key2");
            var value3 = data.GetString("key2");

            var dateString = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");
            Random random = new Random();

            jobData["key1"] = random.Next(1, 20);//Assign a value to the key. The next time you come in for execution, the value obtained is the updated value, not the original value
            jobData["key2"] = dateString;

            return Task.Run(() =>
            {
                using (StreamWriter sw = new StreamWriter(@"C:\Users\Administrator\Desktop\error.log", true, Encoding.UTF8))
                {
                    sw.WriteLine($"{dateString} value1:{value1} value2:{value2}");
                }
                //context.Scheduler.DeleteJob(context.JobDetail.Key);
                //context.Scheduler.Shutdown();
            });
        }
    }

3, Quartz Net composition

Quartz is mainly composed of three parts: job, trigger and schedule.

3.1 tasks

A Job is an executed Job. A Job needs to inherit the IJob interface and implement the Execute method. The parameters executed in the Job are obtained from the parameters of the Execute method.

3.2 trigger

There are two commonly used triggers: SimpleTrigger trigger and CronTrigger trigger.

SimpleTrigger: it can realize simple business, such as triggering execution every few minutes and hours, and limiting the number of executions.

var trigger = TriggerBuilder.Create()
                       .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).WithRepeatCount(5))//Execute 6 times every 2 seconds
                       .UsingJobData("key1", 321)
                       .WithIdentity("trigger", "group")
                       .Build();

Crontrigger: the cron expression contains 7 fields, seconds, minutes, hours, days within months, days within weeks and years (optional).

Examples:

 var trigger = TriggerBuilder.Create()
                       .WithCronSchedule("0 0 0 1 1 ?")// Triggered at 0:00 on January 1 of new year's day every year
                       .UsingJobData("key1", 321)
                       .UsingJobData("key2", "trigger-key2")
                       .WithIdentity("trigger4", "group14")
                       .Build();

"0 * *? *" is triggered at 10:15 a.m. every day

"0 0-5 14 * * ?" Triggered every 1 minute between 2 p.m. and 2:05 p.m. every day

3.3 dispatcher

The scheduler is to bind the task to the trigger and let the trigger execute the task when it is triggered.

Tags: C#

Posted by rockintyler on Sat, 14 May 2022 23:06:53 +0300