Quartz.NET的使用(附源码)
简介
虽然Quartz.NET被园子里的大神们写烂了,自己还是整理了一篇,结尾会附上源码地址。
Quartz.NET是一款功能齐全的开源作业调度框架,小至的应用程序,大到企业系统都可以适用。Quartz是作者James House用JAVA语言编写的,而Quartz.NET是从Quartz移植过来的C#版本。
在一般企业,可以利用Quartz.Net框架做各种的定时任务,例如,数据迁移、跑报表等等。
另外还有一款Hangfire https://www.hangfire.io/,也是作业调度框架,有自带监控web后台,比Quartz.Net更加易用,简单。但是Cron最低只支持到分钟级。然而Hangfire不是今天的主角,有机会再介绍。
简单例子
新建一个控制台项目,通过Nuget管理下载Quartz包
using System;
using System.Collections.Specialized;
using Quartz;
using Quartz.Impl; namespace QuartzDotNetDemo
{
class Program
{
static void Main(string[] args)
{
//创建一个调度器工厂
var props = new NameValueCollection
{
{ "quartz.scheduler.instanceName", "QuartzDotNetDemo" }
};
var factory = new StdSchedulerFactory(props); //获取调度器
var sched = factory.GetScheduler();
sched.Start(); //定义一个任务,关联"HelloJob"
var job = JobBuilder.Create<HelloJob>()
.WithIdentity("myJob", "group1")
.Build(); //由触发器每40秒触发执行一次任务
var trigger = TriggerBuilder.Create()
.WithIdentity("myTrigger", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds()
.RepeatForever())
.Build(); sched.ScheduleJob(job, trigger);
}
} public class HelloJob : IJob
{
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("你好");
}
}
}
一个简单的调度任务流程如下:
概念
有几个重要类和概念需要了解一下:
- IScheduler - 与调度器交互的主要API.
- IJob -由执行任务实现的接口。
- IJobDetail - 定义Job实例
- ITrigger - 按照定义的时间让任务执行的组件.
- JobBuilder - 用于定义或者创建JobDetai
- TriggerBuilder -用于定义或生成触发器实例
他们之间的关系大概如下:
当有空闲线程同时,到了该执行的时间,那么就会由Trigger去触发绑定的Job执行它的Excute方法,假如这次没执行完,却到了下一次的运行时间,如果有空闲线程就仍然会再次执行。但是如果没有空闲线程,会等到腾出空闲的线程才会执行,但是超过quartz.jobStore.misfireThreshold设置的时间就会放弃这次的运行。
当然也可以在Job贴上DisallowConcurrentExecution标签让Job进行单线程跑,避免没跑完时的重复执行。
改造
在第一个简单的demo里是无法良好的在实际中使用,因此我们需要改造一下。
需要的第三方包:
- Autofac version="4.6.2"
- Autofac.Extras.Quartz version="3.4.0"
- Common.Logging version="3.4.1"
- Common.Logging.Core version="3.4.1"
- Common.Logging.Log4Net1213 version="3.4.1"
- log4net version="2.0.3"
- Newtonsoft.Json version="10.0.3"
- Quartz version="2.6.1"
- Topshelf version="4.0.3"
- Topshelf.Autofac version="3.1.1"
- Topshelf.Log4Net version="3.2.0"
- Topshelf.Quartz version="0.4.0.1"
Topshelf
Topshelf是一款为了方便安装部署在Windows系统下而诞生的宿主框架,它基于控制台项目,为开发人员带来更方便的调试和部署。
官网:https://topshelf.readthedocs.io/en/latest/index.html
那我们可以在Program.cs里写入以下代码:
using Topshelf;
using Topshelf.Autofac; namespace QuartzDotNetDemo
{
class Program
{
static void Main(string[] args)
{
HostFactory.Run(config =>
{
config.SetServiceName(JobService.ServiceName);
config.SetDescription("Quartz.NET的demo");
config.UseLog4Net();
config.UseAutofacContainer(JobService.Container); config.Service<JobService>(setting =>
{
JobService.InitSchedule(setting);
setting.ConstructUsingAutofacContainer();
setting.WhenStarted(o => o.Start());
setting.WhenStopped(o => o.Stop());
});
});
}
}
}
JobService
此类用来读取配置信息、初始化调度任务和注入ioc容器
public class JobService
{
#region 初始化
private static readonly ILog Log = LogManager.GetLogger(typeof(JobService)); private const string JobFile = "JobsConfig.xml";
private static readonly string JobNamespceFormat;
public static readonly string ServiceName;
private static readonly Jobdetail[] JobList;
public static IContainer Container; static JobService()
{
var job = JobFile.XmlToObject<JobsConfig>(); ServiceName = job.Quartz.ServiceName;
JobNamespceFormat = job.Quartz.Namespace;
JobList = job.Quartz.JobList.JobDetail; Log.Info("Jobs.xml 初始化完毕"); InitContainer();
}
#endregion /// <summary>
/// 初始化调度任务
/// </summary>
/// <param name="svc"></param>
public static void InitSchedule(ServiceConfigurator<JobService> svc)
{
svc.UsingQuartzJobFactory(Container.Resolve<IJobFactory>); foreach (var job in JobList)
{
svc.ScheduleQuartzJob(q =>
{
q.WithJob(JobBuilder.Create(Type.GetType(string.Format(JobNamespceFormat, job.JobName)))
.WithIdentity(job.JobName, ServiceName)
.Build); q.AddTrigger(() => TriggerBuilder.Create()
.WithCronSchedule(job.Cron)
.Build()); Log.InfoFormat("任务 {0} 已完成调度设置", string.Format(JobNamespceFormat, job.JobName));
});
} Log.Info("调度任务 初始化完毕");
} /// <summary>
/// 初始化容器
/// </summary>
private static void InitContainer()
{
var builder = new ContainerBuilder();
builder.RegisterModule(new QuartzAutofacFactoryModule());
builder.RegisterModule(new QuartzAutofacJobsModule(typeof(JobService).Assembly));
builder.RegisterType<JobService>().AsSelf(); var execDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var files = Directory.GetFiles(execDir, "QuartzDotNetDemo.*.dll", SearchOption.TopDirectoryOnly);
if (files.Length > )
{
var assemblies = new Assembly[files.Length];
for (var i = ; i < files.Length; i++)
assemblies[i] = Assembly.LoadFile(files[i]); builder.RegisterAssemblyTypes(assemblies)
.Where(t => t.GetInterfaces().ToList().Contains(typeof(IService)))
.AsSelf()
.InstancePerLifetimeScope();
} Container = builder.Build();
Log.Info("IOC容器 初始化完毕");
} public bool Start()
{
Log.Info("服务已启动");
return true;
} public bool Stop()
{
Container.Dispose();
Log.Info("服务已关闭");
return false;
}
}
触发器类型
一共有4种:
- WithCalendarIntervalSchedule
- WithCronSchedule
- WithDailyTimeIntervalSchedule
- WithSimpleSchedule
在项目中使用的是WithCronSchedule,因为cron表达式更加灵活、方便。
Cron表达式
字段名 | 是否必填 | 值范围 | 特殊字符 |
---|---|---|---|
Seconds | YES | 0-59 | , - * / |
Minutes | YES | 0-59 | , - * / |
Hours | YES | 0-23 | , - * / |
Day of month | YES | 1-31 | , - * ? / L W |
Month | YES | 1-12 or JAN-DEC | , - * / |
Day of week | YES | 1-7 or SUN-SAT | , - * ? / L # |
Year | NO | empty, 1970-2099 | , - * / |
例子:
"0 0/5 * * * ?"
---- 每5分钟触发一次
"10 0/5 * * * ?
"
-----每5分钟触发一次,每分钟10秒(例如:10:00:10 am,10:05:10,等等)
"0 0/30 8-9 5,20 * ?" ----在每个月的第5到20个小时之间,每隔半小时就会触发一个触发点。请注意,触发器不会在上午10点触发,仅在8点,8点30分,9点和9点30分
BaseJob
我们定义一个BaseJob写入公共处理逻辑,例如:业务逻辑禁用、公共异常日志消息推送等等。再由具体的Job去继承重写基类的ExecuteJob,简单的适配器模式运用。
public abstract class BaseJob : IJob
{
protected readonly CommonService CommonService; protected BaseJob(CommonService commonService)
{
CommonService = commonService;
} public void Execute(IJobExecutionContext context)
{
//公共逻辑
CommonService.Enabled(); //job逻辑
ExecuteJob(context);
} public abstract void ExecuteJob(IJobExecutionContext context);
}
结束
最后按照惯例双手奉上demo源码。https://github.com/SkyChenSky/QuartzDotNetDemo.git
如果错误麻烦在下面评论指出,我会及时修改。
Quartz.NET的使用(附源码)的更多相关文章
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- 使用sqlserver搭建高可用双机热备的Quartz集群部署【附源码】
一般拿Timer和Quartz相比较的,简直就是对Quartz的侮辱,两者的功能根本就不在一个层级上,如本篇介绍的Quartz强大的序列化机制,可以序列到 sqlserver,mysql,当然还可以在 ...
- 在网站开发中很有用的8个 jQuery 效果【附源码】
jQuery 作为最优秀 JavaScript 库之一,改变了很多人编写 JavaScript 的方式.它简化了 HTML 文档遍历,事件处理,动画和 Ajax 交互,而且有成千上万的成熟 jQuer ...
- Web 开发中很实用的10个效果【附源码下载】
在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...
- MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)
前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)
前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...
- 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)
在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...
- jquery自定义插件结合baiduTemplate.js实现异步刷新(附源码)
上一篇记录了BaiduTemplate模板引擎使用示例附源码,在此基础上对使用方法进行了封装 自定义插件jajaxrefresh.js 代码如下: //闭包限定命名空间 (function ($) { ...
- 精选9个值得学习的 HTML5 效果【附源码】
这里精选了一组很酷的 HTML5 效果.HTML5 是现 Web 开发领域的热点, 拥有很多让人期待已久的新特性,特别是在移动端,Web 开发人员可以借助 HTML5 强大功能轻松制作各种交互性强.效 ...
- C#/ASP.NET MVC微信公众号接口开发之从零开发(四) 微信自定义菜单(附源码)
C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发( ...
随机推荐
- birt 集成到现有的web应用中
我们已经有了一个Javaweb应用,现在要实现对报表的集成 我的应用是这个样子的 说明: 1) 这里使用的是birt4.4版本的, 下载birt-runtime-4.4.zip(在官方下载),然 ...
- 升级与修改Nginx
自从上次安装了Nginx后,学到了很多新的东西,比如http2.0... 而且还发现nginx还出了新版本,遂决定升级下,还是那个URL,下载最新版. ./configure --user=www - ...
- JVM菜鸟进阶高手之路一(一次与笨神,阿飞近距离接触修改JVM)
转载请注明原创出处,谢谢! 今天在JVMPocket群里面看见,阿牛发了一个gc截图,之后ak47截图了特别恐怖,我就觉得好奇,去看看服务情况,截图日志如下 关于jstat命令详情可以参考:https ...
- MyEclipse/Eclipse 使用图文详解
引言 某天在群里看到有小伙伴问MyEclipse/Eclipse的一些使用问题,虽然在我看来,问的问题很简单,但是如果对于刚刚学习的人来说,可能使用就不那么友好了.毕竟我在开始使用MyEclipse/ ...
- 关于IOS的屏幕适配(iPhone)——Auto Layout和Size Classes
Auto Layout和Size Classes搭配使用极大的方便了开发者,具体如何使用Auto Layout和Size Classes大家可以参考其他文章或者书籍,这里只提一点,在我们设置Size ...
- LCA问题第二弹
LCA问题第二弹 上次用二分的方法给大家分享了对 LCA 问题的处理,各位应该还能回忆起来上次的方法是由子节点向根节点(自下而上)的处理,平时我们遇到的很多问题都是正向思维处理困难而逆向思维处理比较容 ...
- Https系列之三:让服务器同时支持http、https,基于spring boot
Https系列会在下面几篇文章中分别作介绍: 一:https的简单介绍及SSL证书的生成二:https的SSL证书在服务器端的部署,基于tomcat,spring boot三:让服务器同时支持http ...
- 微信小程序-发送模板消息(C#)
步骤一:获取模板ID 有两个方法可以获取模版ID 通过模版消息管理接口获取模版ID 在微信公众平台手动配置获取模版ID 步骤二:页面的 <form/> 组件,属性report-submit ...
- http://codeforces.com/problemset/problem/594/A
A. Warrior and Archer time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Day1 Python基础学习
一.编程语言分类 1.简介 机器语言:站在计算机的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件 汇编语言:站在计算机的角度,简写的英文标识符取代二进制去编写程序,本质仍然是直接操作 ...