Quartz.NET 是一个功能强大的开源任务调度库,广泛应用于 .NET 平台,用于定时执行任务。无论是简单的定时任务,还是复杂的调度需求,Quartz.NET 都能轻松应对。
官网:http://www.quartz-scheduler.net/
使用场景
- 定时发送邮件:例如,每天定时发送报告邮件。
- 定时备份数据库:例如,每天凌晨自动备份数据库。
- 定时生成报表:例如,每月初生成上个月的销售报表。
- 定时清理缓存:例如,每隔一段时间清理过期缓存。
主要组件
- Scheduler(调度器) :负责触发任务的核心组件。
- Job(任务) :执行特定操作的类,必须实现
IJob
接口。 - Trigger(触发器) :定义任务的执行时间。常见的触发器有
SimpleTrigger
(简单重复间隔)和CronTrigger
(基于 cron 表达式的复杂调度)。 - JobDetail(任务详情) :包含任务执行所需的所有信息,如任务类和关联的作业数据。
基本用法
通过 NuGet 安装
- 打开 Visual Studio 并加载你的项目。
- 右键点击项目名称,选择“管理 NuGet 包”。
- 在 NuGet 包管理器中搜索“Quartz”,选择合适的版本,点击“安装”。
实现任务类
首先,创建一个实现了 IJob 接口的类。该接口包含 Execute 方法,任务运行时会调用此方法。
using Quartz;
using System;
using System.Threading.Tasks;
namespace QuartzExample
{
[DisallowConcurrentExecution] // 禁止并发执行
public class MailJobTest : IJob
{
public async Task Execute(IJobExecutionContext context)
{
try
{
Console.WriteLine("邮箱开始调度");
}
catch (Exception ex)
{
Console.WriteLine($"定时器异常: {ex.Message}");
}
}
}
}
启动调度
接下来,实例化并启动调度程序,并调度要执行的作业。
using Quartz;
using Quartz.Impl;
using System.Threading.Tasks;
namespace QuartzExample
{
public class QuartzScheduler
{
private IScheduler _scheduler;
public async Task StartScheduler()
{
// 创建调度器实例
var factory = new StdSchedulerFactory();
_scheduler = await factory.GetScheduler();
await _scheduler.Start();
// 创建任务
var job = JobBuilder.Create<MailJobTest>()
.WithIdentity("MailJob", "MailGroup")
.Build();
// 创建触发器
var trigger = TriggerBuilder.Create()
.WithIdentity("MailTrigger", "MailTriggerGroup")
.WithCronSchedule("0/5 * * * * ?") // 每5秒执行一次
.Build();
// 调度任务
await _scheduler.ScheduleJob(job, trigger);
}
public async Task StopScheduler()
{
if (_scheduler != null)
{
await _scheduler.Shutdown();
}
}
}
}
调用示例
using System;
using System.Threading.Tasks;
namespace QuartzExample
{
class Program
{
static async Task Main(string[] args)
{
var quartzScheduler = new QuartzScheduler();
await quartzScheduler.StartScheduler();
Console.WriteLine("按任意键停止调度...");
Console.ReadKey();
await quartzScheduler.StopScheduler();
}
}
}
取消任务调度
// 关闭
scheduler1.Shutdown().Wait();
耗时任务处理
对于耗时较长的任务,可以使用 [DisallowConcurrentExecution]
特性,确保任务在上一次执行完成后才会开始下一次执行。
[DisallowConcurrentExecution]
public class LongRunningJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
// 模拟耗时操作
await Task.Delay(5000);
Console.WriteLine("耗时任务完成");
}
}
封装 ExQuartz 方法到类中
为了更好地组织代码并提高可维护性,我们可以将 ExQuartz
方法封装到一个类中。以下是封装后的 QuartzScheduler
类,同时考虑了 scheduler
的存储和访问。
QuartzScheduler 类
using Quartz;
using Quartz.Impl;
using System.Threading.Tasks;
namespace UploadLogiData.Quartzs
{
/// <summary>
/// 封装了 ExLogiQuartz 方法和对 scheduler 的访问
/// </summary>
public class QuartzScheduler
{
/// <summary>
/// 调度器实例
/// </summary>
private IScheduler _scheduler;
/// <summary>
/// 静态定义主窗体(假设 Form1 是主窗体)
/// </summary>
public static Form1 Form { get; set; }
/// <summary>
/// 启动调度器并安排任务
/// </summary>
public async Task ExLogiQuartz()
{
Form.DisplayListboxMsg("检测任务启动!");
// 创建调度器实例
var factory = new StdSchedulerFactory();
_scheduler = await factory.GetScheduler();
await _scheduler.Start();
// 创建第一个任务:LogiDownloadJob,每5秒执行一次
var job1 = JobBuilder.Create<LogiDownloadJob>()
.WithIdentity("LogiJob", "LogiGroup")
.Build();
var trigger1 = TriggerBuilder.Create()
.WithIdentity("LogiTrigger", "LogiTriggerGroup")
.WithCronSchedule("0/5 * * * * ?") // 每5秒执行一次
.Build();
await _scheduler.ScheduleJob(job1, trigger1);
// 创建第二个任务:MailJobTest,每天下午3点10分执行一次
var job2 = JobBuilder.Create<MailJobTest>()
.WithIdentity("MailJob", "MailGroup")
.Build();
var trigger2 = TriggerBuilder.Create()
.WithIdentity("MailTrigger", "MailTriggerGroup")
.WithCronSchedule("0 10 15 * * ?") // 每天下午3点10分执行一次
.Build();
await _scheduler.ScheduleJob(job2, trigger2);
}
/// <summary>
/// 获取调度器实例
/// </summary>
public IScheduler Scheduler => _scheduler;
/// <summary>
/// 关闭调度器
/// </summary>
public async Task ShutdownScheduler()
{
if (_scheduler != null)
{
await _scheduler.Shutdown();
}
}
}
}
调用示例
以下是使用 QuartzScheduler
类的示例代码:
using System;
using System.Threading.Tasks;
namespace UploadLogiData
{
class Program
{
public static async Task Main(string[] args)
{
// 初始化主窗体(假设 Form1 是主窗体)
QuartzScheduler.Form = new Form1();
// 创建 QuartzScheduler 实例
var quartzScheduler = new QuartzScheduler();
// 启动调度器并安排任务
await quartzScheduler.ExLogiQuartz();
Console.WriteLine("调度器已启动,按任意键关闭调度器...");
Console.ReadKey();
// 关闭调度器
await quartzScheduler.ShutdownScheduler();
Console.WriteLine("调度器已关闭。");
}
}
}
Cron 表达式
表达式格式
Quartz.NET 使用 Cron 表达式来定义复杂的调度规则。Cron 表达式由7个字段组成:秒、分、时、日、月、星期、年(可选)。
字段名 | 允许的值 | 允许的特殊字符 |
---|---|---|
秒 | 0-59 | , - * / |
分 | 0-59 | , - * / |
小时 | 0-23 | , - * / |
日 | 1-31 | , - * ? / L W C |
月 | 1-12 或 JAN-DEC | , - * / |
星期 | 1-7 或 SUN-SAT | , - * ? / L C # |
年(可选) | 空或 1970-2099 | , - * / |
表达式例子
表达 | 含义 |
---|---|
0 0 12 * * ? |
每天中午12点(中午)触发 |
0 15 10 ? * * |
每天上午10:15触发 |
0 15 10 * * ? |
每天上午10:15触发 |
0 15 10 * * ? * |
每天上午10:15触发 |
0 15 10 * * ? 2005 |
2005年期间,每天上午10:15触发 |
0 * 14 * * ? |
每天从下午2点开始,直到下午2:59结束,每分钟触发一次 |
0 0/5 14 * * ? |
每天从下午2点开始,直到下午2:55,每5分钟触发一次 |
0 0/5 14,18 * * ? |
每天从下午2点开始到下午2:55结束,每5分钟触发一次,并且每天下午6点开始到下午6:55结束,每5分钟触发一次 |
0 0-5 14 * * ? |
每天从下午2点开始,直到下午2:05结束,每分钟触发一次 |
0 10,44 14 ? 3 WED |
3月的每个星期三下午2:10和2:44 pm触发。 |
0 15 10 ? * MON-FRI |
每个星期一,星期二,星期三,星期四和星期五的上午10:15触发 |
0 15 10 15 * ? |
每个月的15日上午10:15触发 |
0 15 10 L * ? |
每个月的最后一天上午10:15触发 |
0 15 10 L-2 * ? |
每个月的倒数第二个上午10:15触发 |
0 15 10 ? * 6L |
每个月的最后一个星期五上午10:15触发 |
0 15 10 ? * 6L |
每个月的最后一个星期五上午10:15触发 |
0 15 10 ? * 6L 2002-2005 |
在2002、2003、2004和2005年的每个月的最后一个星期五上午10:15触发 |
0 15 10 ? * 6#3 |
每个月的第三个星期五上午10:15触发 |
0 0 12 1/5 * ? |
从每月的第一天开始,每月每5天在中午12点(中午)触发。 |
0 11 11 11 11 ? |
每年11月11日上午11:11触发。 |
0 * * * * ? 每1分钟整点触发一次
0 0 * * * ? 每天每1小时整点触发一次
0 0 10 * * ? 每天10点触发一次
0 2 9 * * ? // 每天9点02分执行一次
0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
0 30 9 1 * ? 每月1号上午9点半
0 15 10 15 * ? 每月15日上午10:15触发
*/5 * * * * ? 每隔5秒执行一次
0 */1 * * * ? 每隔1分钟执行一次
0 0 5-15 * * ? 每天5-15点整点触发
0 0/3 * * * ? 每三分钟触发一次
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0 12 ? * WED 表示每个星期三中午12点
0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
0 0 23 L * ? 每月最后一天23点执行一次
0 15 10 L * ? 每月最后一日的上午10:15触发
0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
0 15 10 * * ? 2005 2005年的每天上午10:15触发
0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
标签:触发,Quartz,15,10,await,调度,scheduler,任务调度 From: https://www.cnblogs.com/ouyangkai/p/18683538/quartz-task-scheduling-zbfejj