Asp.Net Core2.0 基于QuartzNet任务管理系统
2018-03-01 16:47
309 查看
Quartz.NET官网地址:https://www.quartz-scheduler.net/
Quartz.NET文档地址:https://www.quartz-scheduler.net/documentation/index.html
现在
新功能
具有异步/等待支持的基于任务的作业,内部以异步/等待方式工作
支持.NET Core / netstandard 2.0和.NET Framework 4.5.2及更高版本
通过提供程序名称
增加了
从
在插件启动时添加对作业调度XML文件的急切验证的支持
在
变化
作业和插件现在位于独立的程序集
ADO.NET提供者名称已被简化,提供者名称没有版本,例如
API方法已被重新使用,主要使用
调度程序方法已更改为基于任务,请记住等待它们
一些
Quartz API的关键接口和类是:
如果你想添加JSON序列化,只需要以同样的方式添加
2、简单实例,代码如下:
HelloJob内容如下:
执行效果如下:
View Code
总结:
开发已个小项目搞了好久才搞完,期间零零散散的开发,还是太懒散了!
平时积累不够,还是太菜了!!!!!
欢迎各位大佬指导指定我这个新人!
Quartz.NET文档地址:https://www.quartz-scheduler.net/documentation/index.html
Quartz.NET是一个开源的作业调度框架,是
OpenSymphony的
Quartz API的.NET移植,它用C#写成,可用于
winform和
asp.net应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,集群,插件,支持
cron-like表达式等等。
现在
Quartz.NET3.0已支持
Asp.Net Core,3.0新功能如下:
新功能
具有异步/等待支持的基于任务的作业,内部以异步/等待方式工作
支持.NET Core / netstandard 2.0和.NET Framework 4.5.2及更高版本
通过提供程序名称
SQLite-Microsoft支持
Microsoft.Data.Sqlite,旧的提供程序
SQLite也仍然有效
增加了
SQL Server内存优化表和
Quartz.Impl.AdoJobStore.UpdateLockRowSemaphoreMOT的初步支持
Common.Logging从相关性中删除
从
ILMerge进程中删除的C5集合不再需要
在插件启动时添加对作业调度XML文件的急切验证的支持
在
TimeZoneUtil中添加对额外的自定义时区解析器功能的支持
变化
作业和插件现在位于独立的程序集
NuGet包
Quartz.Jobs和
Quartz.Plugins中
ADO.NET提供者名称已被简化,提供者名称没有版本,例如
SqlServer-20 => SqlServer
API方法已被重新使用,主要使用
IReadOnlyCollection,这隐藏了两个
HashSets和List小号
LibLog一直隐藏于内部(ILog等),就像它原本打算的那样
SimpleThreadPool消失了,旧的拥有的线程消失了
调度程序方法已更改为基于任务,请记住等待它们
IJob接口现在返回一个任务
一些
IList属性已更改为
IReadOnlyList以正确反映意图
SQL Server CE支持已被删除
DailyCalendar现在将日期时间用于排除的日期,并具有
ISet接口来访问它们
IObjectSerializer有新的方法,
void Initialize(),必须实现
IInterruptableJob取消了上下文的
CancellationToken
Quartz API的关键接口和类是:
IScheduler- 与调度程序交互的主要API。
IJob- 您希望由调度程序执行的组件实现的接口。
IJobDetail- 用于定义作业的实例。
ITrigger- 定义执行给定Job的时间表的组件。
JobBuilder- 用于定义/构建定义作业实例的
JobDetail实例。
TriggerBuilder- 用于定义/构建触发器实例
一、Quartz.NET基本使用
1、新建Asp.Net Core 项目,使用NuGet添加Quartz,或使用程序包管理器引用,命令如下:Install-Package Quartz
如果你想添加JSON序列化,只需要以同样的方式添加
Quartz.Serialization.Json包。
2、简单实例,代码如下:
using Five.QuartzNetJob.ExecuteJobTask.Service; using Quartz; using Quartz.Impl; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; using System.Threading.Tasks; namespace Five.QuartzNetJob.Web.Controllers { public class TestTask { public async Task StartTestAsync() { try { // 从工厂中获取调度程序实例 NameValueCollection props = new NameValueCollection { { "quartz.serializer.type", "binary" } }; StdSchedulerFactory factory = new StdSchedulerFactory(props); IScheduler scheduler = await factory.GetScheduler(); // 开启调度器 await scheduler.Start(); // 定义这个工作,并将其绑定到我们的IJob实现类 IJobDetail job = JobBuilder.Create<HelloJob>() .WithIdentity("job1", "group1") .Build(); // 触发作业立即运行,然后每10秒重复一次,无限循环 ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartNow() .WithSimpleSchedule(x => x .WithIntervalInSeconds(10) .RepeatForever()) .Build(); // 告诉Quartz使用我们的触发器来安排作业 await scheduler.ScheduleJob(job, trigger); // 等待60秒 await Task.Delay(TimeSpan.FromSeconds(60)); // 关闭调度程序 await scheduler.Shutdown(); } catch (SchedulerException se) { await Console.Error.WriteLineAsync(se.ToString()); } } } }
HelloJob内容如下:
using Quartz; using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; namespace Five.QuartzNetJob.ExecuteJobTask.Service { public class HelloJob : IJob { public Task Execute(IJobExecutionContext context) { Console.Out.WriteLineAsync("Greetings from HelloJob!"); return Task.CompletedTask; } } }
执行效果如下:
using QuartzNet.Entity; using Quartz; using Quartz.Impl; using System; using System.Collections.Specialized; using System.Threading.Tasks; using Five.QuartzNetJob.Utils.Tool; using System.Reflection; using System.Collections.Generic; namespace QuartzNet3.Core { /// <summary> /// 任务调度中心 /// </summary> public class SchedulerCenter { /// <summary> /// 任务调度对象 /// </summary> public static readonly SchedulerCenter Instance; static SchedulerCenter() { Instance = new SchedulerCenter(); } private Task<IScheduler> _scheduler; /// <summary> /// 返回任务计划(调度器) /// </summary> /// <returns></returns> private Task<IScheduler> Scheduler { get { if (this._scheduler != null) { return this._scheduler; } // 从Factory中获取Scheduler实例 NameValueCollection props = new NameValueCollection { { "quartz.serializer.type", "binary" }, //以下配置需要数据库表配合使用,表结构sql地址:https://github.com/quartznet/quartznet/tree/master/database/tables //{ "quartz.jobStore.type","Quartz.Impl.AdoJobStore.JobStoreTX, Quartz"}, //{ "quartz.jobStore.driverDelegateType","Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz"}, //{ "quartz.jobStore.tablePrefix","QRTZ_"}, //{ "quartz.jobStore.dataSource","myDS"}, //{ "quartz.dataSource.myDS.connectionString",AppSettingHelper.MysqlConnection},//连接字符串 //{ "quartz.dataSource.myDS.provider","MySql"}, //{ "quartz.jobStore.useProperties","true"} }; StdSchedulerFactory factory = new StdSchedulerFactory(props); return this._scheduler = factory.GetScheduler(); } } /// <summary> /// 运行指定的计划(映射处理IJob实现类) /// </summary> /// <param name="jobGroup">任务分组</param> /// <param name="jobName">任务名称</param> /// <returns></returns> public async Task<BaseQuartzNetResult> RunScheduleJob<T>(string jobGroup, string jobName) where T : ScheduleManage { BaseQuartzNetResult result; //开启调度器 await this.Scheduler.Result.Start(); //创建指定泛型类型参数指定的类型实例 T t = Activator.CreateInstance<T>(); //获取任务实例 ScheduleEntity scheduleModel = t.GetScheduleModel(jobGroup, jobName); //添加任务 var addResult = AddScheduleJob(scheduleModel).Result; if (addResult.Code == 1000) { scheduleModel.Status = EnumType.JobStatus.已启用; t.UpdateScheduleStatus(scheduleModel); //用给定的密钥恢复(取消暂停)IJobDetail await this.Scheduler.Result.ResumeJob(new JobKey(jobName, jobGroup)); result = new BaseQuartzNetResult { Code = 1000, Msg = "启动成功" }; } else { result = new BaseQuartzNetResult { Code = -1 }; } return result; } /// <summary> /// 添加一个工作调度(映射程序集指定IJob实现类) /// </summary> /// <param name="m"></param> /// <returns></returns> private async Task<BaseQuartzNetResult> AddScheduleJob(ScheduleEntity m) { var result = new BaseQuartzNetResult(); try { //检查任务是否已存在 var jk = new JobKey(m.JobName, m.JobGroup); if (await this.Scheduler.Result.CheckExists(jk)) { //删除已经存在任务 await this.Scheduler.Result.DeleteJob(jk); } //反射获取任务执行类 var jobType = FileHelper.GetAbsolutePath(m.AssemblyName, m.AssemblyName + "." + m.ClassName); // 定义这个工作,并将其绑定到我们的IJob实现类 IJobDetail job = new JobDetailImpl(m.JobName, m.JobGroup, jobType); //IJobDetail job = JobBuilder.CreateForAsync<T>().WithIdentity(m.JobName, m.JobGroup).Build(); // 创建触发器 ITrigger trigger; //校验是否正确的执行周期表达式 if (!string.IsNullOrEmpty(m.Cron) && CronExpression.IsValidExpression(m.Cron)) { trigger = CreateCronTrigger(m); } else { trigger = CreateSimpleTrigger(m); } // 告诉Quartz使用我们的触发器来安排作业 await this.Scheduler.Result.ScheduleJob(job, trigger); result.Code = 1000; } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("添加任务出错{0}", ex.Message)); result.Code = 1001; result.Msg = ex.Message; } return result; } /// <summary> /// 运行指定的计划(泛型指定IJob实现类) /// </summary> /// <param name="jobGroup">任务分组</param> /// <param name="jobName">任务名称</param> /// <returns></returns> public async Task<BaseQuartzNetResult> RunScheduleJob<T, V>(string jobGroup, string jobName) where T : ScheduleManage, new() where V : IJob { BaseQuartzNetResult result; //开启调度器 await this.Scheduler.Result.Start(); //创建指定泛型类型参数指定的类型实例 T t = Activator.CreateInstance<T>(); //获取任务实例 ScheduleEntity scheduleModel = t.GetScheduleModel(jobGroup, jobName); //添加任务 var addResult = AddScheduleJob<V>(scheduleModel).Result; if (addResult.Code == 1000) { scheduleModel.Status = EnumType.JobStatus.已启用; t.UpdateScheduleStatus(scheduleModel); //用给定的密钥恢复(取消暂停)IJobDetail await this.Scheduler.Result.ResumeJob(new JobKey(jobName, jobGroup)); result = new BaseQuartzNetResult { Code = 1000, Msg = "启动成功" }; } else { result = new BaseQuartzNetResult { Code = -1 }; } return result; } /// <summary> /// 添加任务调度(指定IJob实现类) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="m"></param> /// <returns></returns> private async Task<BaseQuartzNetResult> AddScheduleJob<T>(ScheduleEntity m) where T : IJob { var result = new BaseQuartzNetResult(); try { //检查任务是否已存在 var jk = new JobKey(m.JobName, m.JobGroup); if (await this.Scheduler.Result.CheckExists(jk)) { //删除已经存在任务 await this.Scheduler.Result.DeleteJob(jk); } //反射获取任务执行类 // var jobType = FileHelper.GetAbsolutePath(m.AssemblyName, m.AssemblyName + "." + m.ClassName); // 定义这个工作,并将其绑定到我们的IJob实现类 //IJobDetail job = new JobDetailImpl(m.JobName, m.JobGroup, jobType); IJobDetail job = JobBuilder.CreateForAsync<T>().WithIdentity(m.JobName, m.JobGroup).Build(); // 创建触发器 ITrigger trigger; //校验是否正确的执行周期表达式 if (!string.IsNullOrEmpty(m.Cron) && CronExpression.IsValidExpression(m.Cron)) { trigger = CreateCronTrigger(m); } else { trigger = CreateSimpleTrigger(m); } // 告诉Quartz使用我们的触发器来安排作业 await this.Scheduler.Result.ScheduleJob(job, trigger); result.Code = 1000; } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("添加任务出错", ex.Message)); result.Code = 1001; result.Msg = ex.Message; } return result; } /// <summary> /// 暂停指定的计划 /// </summary> /// <param name="jobGroup">任务分组</param> /// <param name="jobName">任务名称</param> /// <param name="isDelete">停止并删除任务</param> /// <returns></returns> public BaseQuartzNetResult StopScheduleJob<T>(string jobGroup, string jobName, bool isDelete = false) where T : ScheduleManage, new() { BaseQuartzNetResult result; try { this.Scheduler.Result.PauseJob(new JobKey(jobName, jobGroup)); if (isDelete) { Activator.CreateInstance<T>().RemoveScheduleModel(jobGroup, jobName); } result = new BaseQuartzNetResult { Code = 1000, Msg = "停止任务计划成功!" }; } catch (Exception ex) { result = new BaseQuartzNetResult { Code = -1, Msg = "停止任务计划失败" }; } return result; } /// <summary> /// 恢复运行暂停的任务 /// </summary> /// <param name="jobName">任务名称</param> /// <param name="jobGroup">任务分组</param> public async void ResumeJob(string jobName, string jobGroup) { try { //检查任务是否存在 var jk = new JobKey(jobName, jobGroup); if (await this.Scheduler.Result.CheckExists(jk)) { //任务已经存在则暂停任务 await this.Scheduler.Result.ResumeJob(jk); await Console.Out.WriteLineAsync(string.Format("任务“{0}”恢复运行", jobName)); } } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("恢复任务失败!{0}", ex)); } } /// <summary> /// 停止任务调度 /// </summary> public async void StopScheduleAsync() { try { //判断调度是否已经关闭 if (!this.Scheduler.Result.IsShutdown) { //等待任务运行完成 await this.Scheduler.Result.Shutdown(); await Console.Out.WriteLineAsync("任务调度停止!"); } } catch (Exception ex) { await Console.Out.WriteLineAsync(string.Format("任务调度停止失败!", ex)); } } /// <summary> /// 创建类型Simple的触发器 /// </summary> /// <param name="m"></param> /// <returns></returns> private ITrigger CreateSimpleTrigger(ScheduleEntity m) { //作业触发器 if (m.RunTimes > 0) { return TriggerBuilder.Create() .WithIdentity(m.JobName, m.JobGroup) .StartAt(m.BeginTime)//开始时间 .EndAt(m.EndTime)//结束数据 .WithSimpleSchedule(x => x .WithIntervalInSeconds(m.IntervalSecond)//执行时间间隔,单位秒 .WithRepeatCount(m.RunTimes))//执行次数、默认从0开始 .ForJob(m.JobName, m.JobGroup)//作业名称 .Build(); } else { return TriggerBuilder.Create() .WithIdentity(m.JobName, m.JobGroup) .StartAt(m.BeginTime)//开始时间 .EndAt(m.EndTime)//结束数据 .WithSimpleSchedule(x => x .WithIntervalInSeconds(m.IntervalSecond)//执行时间间隔,单位秒 .RepeatForever())//无限循环 .ForJob(m.JobName, m.JobGroup)//作业名称 .Build(); } } /// <summary> /// 创建类型Cron的触发器 /// </summary> /// <param name="m"></param> /// <returns></returns> private ITrigger CreateCronTrigger(ScheduleEntity m) { // 作业触发器 return TriggerBuilder.Create() .WithIdentity(m.JobName, m.JobGroup) .StartAt(m.BeginTime)//开始时间 .EndAt(m.EndTime)//结束时间 .WithCronSchedule(m.Cron)//指定cron表达式 .ForJob(m.JobName, m.JobGroup)//作业名称 .Build(); } } }
View Code
总结:
开发已个小项目搞了好久才搞完,期间零零散散的开发,还是太懒散了!
平时积累不够,还是太菜了!!!!!
欢迎各位大佬指导指定我这个新人!
相关文章推荐
- Asp.Net Core2.0 基于QuartzNet任务管理系统
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(3)
- Asp.Net Core 基于QuartzNet任务管理系统(这是一篇用来水的随笔)
- Asp.Net Core 2.0 项目实战(11) 基于OnActionExecuting全局过滤器,页面操作权限过滤控制到按钮级
- Asp.Net Core 2.0 项目实战(9) 日志记录,基于Nlog或Microsoft.Extensions.Logging的实现及调用实例
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)
- Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录
- asp.net core 2.0 web api基于JWT自定义策略授权
- asp.net core 2.0 web api基于JWT自定义策略授权
- Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录
- asp.net core 2.0 web api基于JWT自定义策略授权
- 一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移
- 一起学ASP.NET Core 2.0学习笔记(二)- ef core2.0 及mysql provider 、Fluent API相关配置及迁移
- 从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD
- ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
- ASP.NET Core 2.0系列学习笔记-ORM框架之Dapper
- ASP.NET Core 2.0 : 三. 项目结构
- 搭建连接MySql的三层架构的ASP.NetCore2.0的WebApi
- Asp.Net Core 2.0 项目实战(4)ADO.NET操作数据库封装、 EF Core操作及实例
- [译]ASP.NET Core 2.0 布局页面