首页 > 编程语言 >Net6 定时调度Quartz.AspNetCore(3.5.0)的使用

Net6 定时调度Quartz.AspNetCore(3.5.0)的使用

时间:2022-10-20 16:36:36浏览次数:75  
标签:Quartz AspNetCore 调度 Job 3.5 Extensions var using public

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

1、概述

Quartz.Net是根据Java的Quartz用C#改写而来,Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等。 Quartz.NET允许开发人员根据时间间隔来调度作业。它有很多特征如:数据库支持,集群,插件,支持cron-like表达式等等。

2、参考

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

官方学习文档:http://www.quartz-scheduler.net/documentation/index.html

3、Quartz.Net说明

Quartz主要有三部分组成任务(Job)、触发器(Trigger)和调度器(Schedule)。

3.1、作业

Job就是执行的作业,Job需要继承IJob接口,实现Execute方法。Job中执行的参数从Execute方法的参数中获取。

3.2、触发器

触发器常用的有两种:SimpleTrigger触发器和CronTrigger触发器。

SimpleTrigger

 实现简单业务,如每隔几分钟,几小时触发执行,并限制执行次数。

  • 重复执行:WithRepeatCount()/RepeatForever()
  • 设置间隔时间:WithInterval()
  • 定时执行:StartAt()/StartNow()
  • 设定优先级:WithPriority(),默认为5
var trigger = TriggerBuilder.Create()
                       .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).WithRepeatCount(5))//间隔2秒 执行6次
                       .UsingJobData("key1", 321)
                       .WithIdentity("trigger", "group")
                       .Build();

CronTrigger

CornTrigger需要接合Corn表达式

常用cron表达式

  • */10 * * * * ? 每隔10秒执行一次
  • 0 */5 * * * ? 每隔5分钟执行一次
  • 0 2,22,32 * * * ? 在2分、22分、32分执行一次
  • 0 0 4-8 * * ? 每天4-8点整点执行一次
  • 0 0 2 * * ? 每天凌晨2点执行一次
  • 0 0 2 1 * ? 每月1号凌晨2点执行一次

cron表达式生成器

现在也有许多在线的cron表达式生成器:

https://cron.qqe2.com/

https://www.toolzl.com/tools/croncreate.html

            var trigger = TriggerBuilder.Create().StartNow()
                            .WithCronSchedule("0/2 * * * * ? *")//每两秒执行一次
                            .Build();

3.3、调度器

调度器就是将任务和触发器绑定,让触发器触发的时候去执行任务。

3.4、参数说明

  • SetJobData:设置JobData

  • StoreDurably:孤立存储,指即使该JobDetail没有关联的Trigger,也会进行存储

  • RequestRecovery:请求恢复,指应用崩溃后再次启动,会重新执行该作业

  • WithIdentity:作业的唯一标识

  • WithDescription:作业的描述信息

除此之外,Quartz.Net还支持两个非常有用的特性:

  • DisallowConcurrentExecution:禁止并行执行,该特性是针对JobDetail生效的

  • PersistJobDataAfterExecution:在执行完成后持久化JobData,该特性是针对Job类型生效的,意味着所有使用该Job的JobDetail都会在执行完成后持久化JobData。

4、新建控制台应用程序

项目清单如下

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
    <PackageReference Include="Quartz.AspNetCore" Version="3.5.0" />
      <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
      <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
      <PackageReference Include="NLog.Extensions.Logging" Version="5.0.4" />
  </ItemGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>
View Code

4.1、简单时间间隔作业

using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Logging;
using System;

namespace BatteryService // Note: actual namespace depends on the project name.
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json", true, true);
            var ConfigRoot = builder.Build();//根节点
            IServiceCollection Services = new ServiceCollection(); 
            // 
            Services.AddLogging(log => { log.AddConsole(); log.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information); }); 
            Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();//注册ISchedulerFactory的实例。
            Services.AddScoped<QuartzService>();//注册 QuartzService 的实例。
            using (ServiceProvider provider = Services.BuildServiceProvider())
            {
                var service = provider.GetService<QuartzService>();
                await service.with2Seconds();
            };
            CreateHostBuilder(args).Run();
        }

        public static IHost CreateHostBuilder(string[] args)
        {
            var builder = Host.CreateDefaultBuilder(args)
                 .ConfigureServices((hostContext, services) =>
                 {
                     //services.AddHostedService<IotService>();
                 }).UseWindowsService();
            var host = builder.Build();

            return host;
        }
    }

    public class QuartzService
    { 
        private readonly ISchedulerFactory _schedulerFactory; 
        private IScheduler _scheduler;
        private readonly ILogger<QuartzService> logger;
        public QuartzService(ISchedulerFactory schedulerFactory, ILogger<QuartzService> logger)
        {
            _schedulerFactory = schedulerFactory;
            this.logger = logger;
        }

        public async Task with2Seconds()
        {
          
            //通过调度工厂获得调度器
            _scheduler = await _schedulerFactory.GetScheduler(); 
            //开启调度器
            await _scheduler.Start();
            logger.LogInformation("调度器开始工作");
            //创建一个触发器
            var trigger = TriggerBuilder.Create().StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).RepeatForever())//每两秒执行一次
                            .Build();
            //创建任务
            var jobDetail = JobBuilder.Create<MyJob>()
                            .WithIdentity("job1", "group")
                            .Build();
            //将触发器和任务器绑定到调度器中
            await _scheduler.ScheduleJob(jobDetail, trigger);
        }
    }
    [DisallowConcurrentExecution]//禁止并行执行,该特性是针对JobDetail生效的
    public class MyJob : IJob
    {  
        public Task Execute(IJobExecutionContext context)
        {
            return Task.Run(() =>
            {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); 
            });
        }
    } 
}  
View Code

 4.2、可以传递参数的简单作业(使用了特性【DisallowConcurrentExecution】防并发作业)

using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Logging;
using System;

namespace BatteryService // Note: actual namespace depends on the project name.
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json", true, true);
            var ConfigRoot = builder.Build();//根节点
            IServiceCollection Services = new ServiceCollection(); 
            // 
            Services.AddLogging(log => { log.AddConsole(); log.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information); }); 
            Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();//注册ISchedulerFactory的实例。
            Services.AddScoped<QuartzService>();//注册 QuartzService 的实例。
            using (ServiceProvider provider = Services.BuildServiceProvider())
            {
                var service = provider.GetService<QuartzService>();
                await service.with2Seconds();
            };
            CreateHostBuilder(args).Run();
        }

        public static IHost CreateHostBuilder(string[] args)
        {
            var builder = Host.CreateDefaultBuilder(args)
                 .ConfigureServices((hostContext, services) =>
                 {
                     //services.AddHostedService<IotService>();
                 }).UseWindowsService();
            var host = builder.Build();

            return host;
        }
    }

    public class QuartzService
    { 
        private readonly ISchedulerFactory _schedulerFactory; 
        private IScheduler _scheduler;
        private readonly ILogger<QuartzService> logger;
        public QuartzService(ISchedulerFactory schedulerFactory, ILogger<QuartzService> logger)
        {
            _schedulerFactory = schedulerFactory;
            this.logger = logger;
        }

        public async Task with2Seconds()
        {
          
            //通过调度工厂获得调度器
            _scheduler = await _schedulerFactory.GetScheduler(); 
            //开启调度器
            await _scheduler.Start();
            logger.LogInformation("调度器开始工作");
            //创建一个触发器
            var trigger = TriggerBuilder.Create().StartNow().UsingJobData("Trigger", "我是在Trigger中设置的参数").UsingJobData("TriggerParmCount", 1)
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).WithRepeatCount(1))//每两秒执行一次
                            .Build();
            //创建任务
            var jobDetail = JobBuilder.Create<MyJob>()
                .UsingJobData("Job_1", "我是在Job中设置的参数")
                .UsingJobData("Job_2", "我是在Job中设置的参数")
                .UsingJobData("ParmCount", 2)
                .WithIdentity("jobName", "group")
                .Build();
            //将触发器和任务器绑定到调度器中
            await _scheduler.ScheduleJob(jobDetail, trigger);
        }
    }
    [DisallowConcurrentExecution]//禁止并行执行,该特性是针对JobDetail生效的
    public class MyJob : IJob
    {  
        public Task Execute(IJobExecutionContext context)
        {
            var jobData = context.JobDetail.JobDataMap;//获取Job中的参数 
            var triggerData = context.Trigger.JobDataMap;//获取Trigger中的参数
            var allData = context.MergedJobDataMap;//获取Job和Trigger中合并的参数
            var Trigger = triggerData.GetString("Trigger");
            int TriggerParmCount = triggerData.GetInt("TriggerParmCount");

            var Job_1 = triggerData.GetString("Job_1");
            var Job_2 = triggerData.GetString("Job_2");
            int ParmCount = triggerData.GetInt("ParmCount");

            return Task.Run(() =>
            {
                foreach (var item in jobData)
                {
                    Console.WriteLine($"Job中的参数,键为:{item.Key}值为:{item.Value}");
                }
                Console.WriteLine("-----------------------------------------------");
                foreach (var item in triggerData)
                {
                    Console.WriteLine($"Trigger中的参数,键为:{item.Key}值为:{item.Value}");
                }
                Console.WriteLine("-----------------------------------------------");
                foreach (var item in allData)
                {
                    Console.WriteLine($"Job和Trigger中的所有参数,键为:{item.Key}值为:{item.Value}");
                }
            });
        }
    } 
}  
View Code

 4.3、可变参数简单作业(使用了特性【PersistJobDataAfterExecution】存储JobDataMap副本)

using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Logging;
using System;

namespace BatteryService // Note: actual namespace depends on the project name.
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json", true, true);
            var ConfigRoot = builder.Build();//根节点
            IServiceCollection Services = new ServiceCollection(); 
            // 
            Services.AddLogging(log => { log.AddConsole(); log.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information); }); 
            Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();//注册ISchedulerFactory的实例。
            Services.AddScoped<QuartzService>();//注册 QuartzService 的实例。
            using (ServiceProvider provider = Services.BuildServiceProvider())
            {
                var service = provider.GetService<QuartzService>();
                await service.with2Seconds();
            };
            CreateHostBuilder(args).Run();
        }

        public static IHost CreateHostBuilder(string[] args)
        {
            var builder = Host.CreateDefaultBuilder(args)
                 .ConfigureServices((hostContext, services) =>
                 {
                     //services.AddHostedService<IotService>();
                 }).UseWindowsService();
            var host = builder.Build();

            return host;
        }
    }

    public class QuartzService
    { 
        private readonly ISchedulerFactory _schedulerFactory; 
        private IScheduler _scheduler;
        private readonly ILogger<QuartzService> logger;
        public QuartzService(ISchedulerFactory schedulerFactory, ILogger<QuartzService> logger)
        {
            _schedulerFactory = schedulerFactory;
            this.logger = logger;
        }

        public async Task with2Seconds()
        {
          
            //通过调度工厂获得调度器
            _scheduler = await _schedulerFactory.GetScheduler(); 
            //开启调度器
            await _scheduler.Start();
            logger.LogInformation("调度器开始工作");
            //创建一个触发器
            var trigger = TriggerBuilder.Create().StartNow()
                .UsingJobData("name", "陈卧龙")
                .UsingJobData("sex", "男")
                .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).WithRepeatCount(9))//每两秒执行一次 共执行10次
                .Build();
            //创建任务
            var jobDetail = JobBuilder.Create<MyJob>()
                .UsingJobData("age", 28)
                .UsingJobData("weight", 70) 
                .WithIdentity("jobName", "group")
                .Build();
            //将触发器和任务器绑定到调度器中
            await _scheduler.ScheduleJob(jobDetail, trigger);
        }
    }
    [PersistJobDataAfterExecution]// 更新JobDetail的JobDataMap的存储副本,以便下一次执行这个任务接收更新的值而不是原始存储的值
    public class MyJob : IJob
    {  
        public Task Execute(IJobExecutionContext context)
        { 
            var allData = context.MergedJobDataMap;//获取Job和Trigger中合并的参数
            var name = allData.GetString("name");
            var sex = allData.GetString("sex"); 
            var age = allData.GetInt("age");
            var weight = allData.GetInt("weight");
            Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            Console.WriteLine($"原始参数为,姓名:{name},性别:{sex},年龄:{age},体重:{weight}");

            allData["name"] = name + "_" + new Random().Next(1, 10);
            allData["sex"] = sex + "_" + new Random().Next(1, 10);
            allData["age"] = new Random().Next(20, 100);
            allData["weight"] = new Random().Next(60, 100);
            return Task.Run(() =>
            {  
                foreach (var item in allData)
                {
                    Console.WriteLine($"改变后的参数,键为:{item.Key}值为:{item.Value}");
                }
                Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            });
        }
    } 
}  
View Code

 4.4、Corn表达式作业调度

corn表示式和简单调度的区别是:一个使用固定时间间隔作业,比较简单。一个可以通过corn表达式进行复杂的时间场景调度

现在也有许多在线的cron表达式生成器:

https://cron.qqe2.com/

https://www.toolzl.com/tools/croncreate.html

 

每月最后一天23:59分执行

日部分截图

 

 

 小时部分截图

 

 分钟部分截图

 

 秒部分截图

 

 

 最终生成的Corn 表达式为:0 59 23 L * ? *

示例代码如下:

        public async Task with2Seconds()
        {
          
            //通过调度工厂获得调度器
            _scheduler = await _schedulerFactory.GetScheduler(); 
            //开启调度器
            await _scheduler.Start();
            logger.LogInformation("调度器开始工作");
            //创建一个触发器
            var trigger = TriggerBuilder.Create().StartNow().WithCronSchedule("0 59 23 L * ? *") //每月月底23.59分执行
                .UsingJobData("name", "陈卧龙")
                .UsingJobData("sex", "男")  
                .Build();
            //创建任务
            var jobDetail = JobBuilder.Create<MyJob>()
                .UsingJobData("age", 28)
                .UsingJobData("weight", 70) 
                .WithIdentity("jobName", "group")
                .Build();
            //将触发器和任务器绑定到调度器中
            await _scheduler.ScheduleJob(jobDetail, trigger);
        }
View Code

核心配置:

  var trigger = TriggerBuilder.Create().StartNow().WithCronSchedule("0 59 23 L * ? *") //每月月底23.59分执行
                .UsingJobData("name", "陈卧龙")
                .UsingJobData("sex", "男")  
                .Build();

@天才卧龙的博科人、

 

标签:Quartz,AspNetCore,调度,Job,3.5,Extensions,var,using,public
From: https://www.cnblogs.com/chenwolong/p/NetCoreQuartz.html

相关文章

  • React + Springboot + Quartz,从0实现Excel报表自动化
    一、项目背景企业日常工作中需要制作大量的报表,比如商品的销量、销售额、库存详情、员工打卡信息、保险报销、办公用品采购、差旅报销、项目进度等等,都需要制作统计图表以......
  • vmp3.5 指令分析
    目录概述结构流程分析vm_entryvm_context_initvm_handlevm_stack_restorevm_exit举例_RTC_CheckEsp()add(1,5c)参考链接概述结构vm_context(vm寄存器)vm_stack(vm栈)vm......
  • Quartz
    介绍本文介绍Java中的一个定时器框架Quartz。触发器[captionid="attachment_4571"align="aligncenter"width="377"]​​​​trigger_class_tree[/caption]......
  • 【ASP.NET Core Swagger】3、注释(Swashbuckle.AspNetCore.Annotations)
    Swashbuckle.AspNetCore.Annotations包括一组可应用于Controller、Action和Model的自定义属性,以丰富生成的Swagger安装Nugetinstall-packageSwashbuckle.AspNetCore.An......
  • 从零开始游戏开发——3.5 纹理基础
    之前的小节,我们显示了使用木箱子外观的三角形,纹理可以极大丰富物体的表现,在这节中,我们将介绍一张图像是如何做为纹理进行显示的,最终实现下图效果:首先,我们拥有一张.tg......
  • Photoshop 2022 for Mac(ps 2022最新版)v23.5.1永久激活版mac/win
    Photoshop2022新功能有哪些?Photoshop简称ps,它是一款专业图像处理软件,此次更新软件可选择项目云服务生成更准确和高质量的图像;软件界面也有了新的中性UI颜色模式,视觉效果更......
  • AspNetCore中 使用 Grpc 简单Demo
    为什么要用Grpc跨语言进行,调用服务,获取跨服务器调用等目前我的需要使用我的抓取端是go写的查询端用Net6写的导致很多时候我需要把一些临时数据写入到Redis在两......
  • ESP32开发环境搭建 IDF3.3.5+VScode
    1、 软件准备:①ESP-IDF:包含ESP32API和用于操作工具链的脚本。②工具链msys32:用于编译ESP32应用程序。③编辑工具VisualStudioCode  注意:工具链和ESP-IDF需......
  • quartz顺序执行任务
    //创建计划链表JobChainingJobListenerlistener=newJobChainingJobListener("JobLink");IJobDetailj1=JobBu......
  • 【问题】 Cocos3.5.2 左边和上方有黑边,任意点一下才能对齐
    版本:3.5.2 背景图是纯蓝色并且widget是适配全屏的,直接运行时,可以看到左边和上方有黑边。   任意点一下屏幕,背景图会上移,上方黑边消失,但是左边黑边还在。 ......