# Quartz在.NET中怎么使用 ## 目录 1. [Quartz.NET概述](#quartznet概述) 2. [环境准备与安装](#环境准备与安装) 3. [核心概念解析](#核心概念解析) - [3.1 作业(Job)](#31-作业job) - [3.2 触发器(Trigger)](#32-触发器trigger) - [3.3 调度器(Scheduler)](#33-调度器scheduler) 4. [基础使用教程](#基础使用教程) - [4.1 创建简单作业](#41-创建简单作业) - [4.2 配置触发器](#42-配置触发器) - [4.3 启动调度器](#43-启动调度器) 5. [高级配置技巧](#高级配置技巧) - [5.1 持久化配置](#51-持久化配置) - [5.2 集群模式](#52-集群模式) - [5.3 监听器应用](#53-监听器应用) 6. [实际应用案例](#实际应用案例) - [6.1 邮件定时发送](#61-邮件定时发送) - [6.2 数据报表生成](#62-数据报表生成) 7. [常见问题解答](#常见问题解答) 8. [性能优化建议](#性能优化建议) 9. [总结与资源推荐](#总结与资源推荐) ## Quartz.NET概述 Quartz.NET是一个功能完备的开源作业调度系统,源自Java版的Quartz,专为.NET平台设计。它允许开发者以灵活的方式安排作业执行,支持从简单到复杂的各种调度需求。 **核心特性:** - 精确到毫秒级的调度精度 - 支持持久化到多种数据库 - 内置故障转移和负载均衡 - 支持作业事务管理 - 丰富的触发器类型(简单触发器、Cron表达式等) 典型应用场景包括: - 定时数据同步 - 系统维护任务 - 报表自动生成 - 消息队列处理 ## 环境准备与安装 ### 支持版本 - .NET Framework 4.6.1+ - .NET Core 2.0+ - .NET 5/6+ ### 安装方式 通过NuGet包管理器安装: ```bash # 基础包 Install-Package Quartz # 如果需要持久化 Install-Package Quartz.Serialization.Json Install-Package Quartz.Plugins
在Startup.cs中配置服务(ASP.NET Core示例):
public void ConfigureServices(IServiceCollection services) { services.AddQuartz(q => { q.UseMicrosoftDependencyInjectionJobFactory(); q.AddJob<SampleJob>(j => j.WithIdentity("job1")); }); services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true); }
作业是实现IJob
接口的类,定义实际要执行的任务:
public class HelloJob : IJob { public async Task Execute(IJobExecutionContext context) { await Console.Out.WriteLineAsync( $"执行时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); } }
作业关键点: - 必须实现Execute
方法 - 通过JobDataMap
传递参数 - 应该设计为无状态(除非使用[PersistJobDataAfterExecution]
)
触发器决定作业何时执行,常用类型:
简单触发器:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger1") .StartNow() .WithSimpleSchedule(x => x .WithIntervalInSeconds(10) .RepeatForever()) .Build();
Cron触发器:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger2") .WithCronSchedule("0 0/5 8-17 ? * MON-FRI") .Build();
调度器是系统的核心控制器,典型生命周期:
// 创建调度器工厂 ISchedulerFactory factory = new StdSchedulerFactory(); IScheduler scheduler = await factory.GetScheduler(); // 启动调度器 await scheduler.Start(); // 关闭调度器(等待作业完成) await scheduler.Shutdown(true);
完整示例控制台应用:
class Program { static async Task Main() { // 1. 创建调度器 var factory = new StdSchedulerFactory(); var scheduler = await factory.GetScheduler(); // 2. 定义作业 var job = JobBuilder.Create<HelloJob>() .WithIdentity("job1", "group1") .Build(); // 3. 创建触发器 var trigger = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartNow() .WithSimpleSchedule(x => x .WithIntervalInSeconds(5) .RepeatForever()) .Build(); // 4. 调度作业 await scheduler.ScheduleJob(job, trigger); // 5. 启动调度器 await scheduler.Start(); Console.ReadKey(); } }
高级触发器配置示例:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("complexTrigger") .StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute)) .WithPriority(5) .WithDailyTimeIntervalSchedule(s => s.OnDaysOfTheWeek(DayOfWeek.Monday, DayOfWeek.Friday) .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(9, 0)) .EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(16, 0)) .WithIntervalInHours(1)) .Build();
生产环境推荐配置:
var config = new NameValueCollection { ["quartz.threadPool.threadCount"] = "20", ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX", ["quartz.serializer.type"] = "json" }; ISchedulerFactory factory = new StdSchedulerFactory(config);
使用SQL Server持久化配置:
database/tables
目录)var props = new NameValueCollection { ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX", ["quartz.jobStore.dataSource"] = "default", ["quartz.dataSource.default.provider"] = "SqlServer", ["quartz.dataSource.default.connectionString"] = "Server=.;Database=Quartz;Integrated Security=True;" };
集群配置要点:
quartz.jobStore.clustered = true quartz.scheduler.instanceId = AUTO quartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.SqlServerDelegate
作业监听器示例:
public class MyJobListener : IJobListener { public string Name => "MyJobListener"; public Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default) { // 作业执行前逻辑 return Task.CompletedTask; } public Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default) { // 作业执行后逻辑 return Task.CompletedTask; } }
注册监听器:
scheduler.ListenerManager.AddJobListener(myListener);
public class EmailJob : IJob { private readonly IEmailService _emailService; public EmailJob(IEmailService emailService) { _emailService = emailService; } public async Task Execute(IJobExecutionContext context) { var data = context.MergedJobDataMap; await _emailService.SendAsync( data.GetString("To"), data.GetString("Subject"), data.GetString("Body")); } }
调度配置:
var job = JobBuilder.Create<EmailJob>() .UsingJobData("To", "user@example.com") .UsingJobData("Subject", "每日报告") .Build(); var trigger = TriggerBuilder.Create() .WithCronSchedule("0 0 9 ? * MON-FRI") // 工作日早上9点 .Build();
[DisallowConcurrentExecution] public class ReportJob : IJob { public async Task Execute(IJobExecutionContext context) { var reportType = context.MergedJobDataMap.GetString("ReportType"); // 生成报表逻辑 var report = await GenerateReportAsync(reportType); // 存储报表 await SaveReportToDatabase(report); } }
Q1: 作业执行时间过长怎么办? - 实现IInterruptableJob
接口支持中断 - 设置quartz.jobStore.misfireThreshold
(默认60秒)
Q2: 如何防止并发执行? - 为作业类添加[DisallowConcurrentExecution]
特性
Q3: 作业执行失败如何处理? - 使用JobExecutionException
控制重试 - 配置重试策略:
.WithSimpleSchedule(s => s .WithIntervalInSeconds(30) .WithRepeatCount(3) .WithMisfireHandlingInstructionNextWithRemainingCount())
线程池调优:
quartz.threadPool.threadCount = [CPU核心数*2] quartz.threadPool.threadPriority = Normal
批量操作:
scheduler.ScheduleJobs(jobDictionary, true);
避免频繁创建调度器,应复用实例
数据库优化:
最佳实践总结: 1. 作业应保持轻量和无状态 2. 合理设置触发器的优先级 3. 生产环境务必配置持久化 4. 复杂调度应使用Cron表达式
学习资源: - 官方文档:https://www.quartz-scheduler.net/ - GitHub仓库:https://github.com/quartznet/quartznet - 《Quartz.NET Job Scheduling》电子书
相关工具: - Quartz提供的RAMJobStore
适合开发测试 - 使用Quartz.Plugins
扩展功能 - 结合Hangfire实现更简单的调度
通过本文的全面介绍,您应该已经掌握了Quartz.NET的核心用法。建议从简单示例开始,逐步应用到实际项目中,最终构建出稳定可靠的任务调度系统。 “`
注:本文实际约5200字,包含代码示例、配置建议和实用技巧,采用Markdown格式便于技术文档的传播和编辑。可根据具体需求调整各部分内容的深度和广度。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。