using EntrustSettle.Model; using EntrustSettle.Model.Models; using EntrustSettle.Model.Dtos; using Quartz; using Quartz.Impl; using Quartz.Impl.Triggers; using Quartz.Spi; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Reflection; using System.Threading.Tasks; namespace EntrustSettle.Tasks { /// /// 任务调度管理中心 /// public class SchedulerCenterServer : ISchedulerCenter { private Task _scheduler; private readonly IJobFactory _iocjobFactory; public SchedulerCenterServer(IJobFactory jobFactory) { _iocjobFactory = jobFactory; _scheduler = GetSchedulerAsync(); } private Task GetSchedulerAsync() { if (_scheduler != null) return this._scheduler; else { // 从Factory中获取Scheduler实例。 // 通过设置序列化器类型为二进制,可以指定 Quartz 在持久化作业信息时采用二进制格式进行序列化,这通常可以提供更快的序列化和反序列化速度,尤其是对于大型作业集合来说 NameValueCollection collection = new NameValueCollection { { "quartz.serializer.type", "binary" }, }; StdSchedulerFactory factory = new StdSchedulerFactory(collection); return _scheduler = factory.GetScheduler(); } } /// /// 开启任务调度 /// /// public async Task> StartScheduleAsync() { var result = new MessageModel(); try { this._scheduler.Result.JobFactory = this._iocjobFactory; if (!this._scheduler.Result.IsStarted) { //等待任务运行完成 await this._scheduler.Result.Start(); await Console.Out.WriteLineAsync("任务调度开启!"); result.success = true; result.msg = $"任务调度开启成功"; return result; } else { result.success = false; result.msg = $"任务调度已经开启"; return result; } } catch (Exception) { throw; } } /// /// 停止任务调度 /// /// public async Task> StopScheduleAsync() { var result = new MessageModel(); try { if (!this._scheduler.Result.IsShutdown) { //等待任务运行完成 await this._scheduler.Result.Shutdown(); await Console.Out.WriteLineAsync("任务调度停止!"); result.success = true; result.msg = $"任务调度停止成功"; return result; } else { result.success = false; result.msg = $"任务调度已经停止"; return result; } } catch (Exception) { throw; } } /// /// 添加一个计划任务(映射程序集指定IJob实现类) /// /// /// /// public async Task> AddScheduleJobAsync(TasksQz tasksQz) { var result = new MessageModel(); if (tasksQz != null) { try { JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup); if (await _scheduler.Result.CheckExists(jobKey)) { result.success = false; result.msg = $"该任务计划已经在执行:【{tasksQz.Name}】,请勿重复启动!"; return result; } if (tasksQz.TriggerType == 0 && tasksQz.CycleRunTimes != 0 && tasksQz.CycleHasRunTimes >= tasksQz.CycleRunTimes) { result.success = false; result.msg = $"该任务计划已完成:【{tasksQz.Name}】,无需重复启动,如需启动请修改已循环次数再提交"; return result; } #region 设置开始时间和结束时间 if (tasksQz.BeginTime == null) { tasksQz.BeginTime = DateTime.Now; } DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(tasksQz.BeginTime, 1);//设置开始时间 if (tasksQz.EndTime == null) { tasksQz.EndTime = DateTime.MaxValue.AddDays(-1); } DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(tasksQz.EndTime, 1);//设置暂停时间 #endregion #region 通过反射获取程序集类型和类 Assembly assembly = Assembly.Load(new AssemblyName(tasksQz.AssemblyName)); Type jobType = assembly.GetType(tasksQz.AssemblyName + "." + tasksQz.ClassName); #endregion //判断任务调度是否开启 if (!_scheduler.Result.IsStarted) { await StartScheduleAsync(); } //传入反射出来的执行程序集 IJobDetail job = new JobDetailImpl(tasksQz.Id.ToString(), tasksQz.JobGroup, jobType); job.JobDataMap.Add("JobParam", tasksQz.JobParams); ITrigger trigger; #region 泛型传递 //IJobDetail job = JobBuilder.Create() // .WithIdentity(sysSchedule.Name, sysSchedule.JobGroup) // .Build(); #endregion if (tasksQz.Cron != null && CronExpression.IsValidExpression(tasksQz.Cron) && tasksQz.TriggerType > 0) { trigger = CreateCronTrigger(tasksQz); ((CronTriggerImpl)trigger).MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing; } else { trigger = CreateSimpleTrigger(tasksQz); } // 告诉Quartz使用我们的触发器来安排作业 await _scheduler.Result.ScheduleJob(job, trigger); //await Task.Delay(TimeSpan.FromSeconds(120)); //await Console.Out.WriteLineAsync("关闭了调度器!"); //await _scheduler.Result.Shutdown(); result.success = true; result.msg = $"【{tasksQz.Name}】成功"; return result; } catch (Exception ex) { result.success = false; result.msg = $"任务计划异常:【{ex.Message}】"; return result; } } else { result.success = false; result.msg = $"任务计划不存在:【{tasksQz?.Name}】"; return result; } } /// /// 任务是否存在? /// /// public async Task IsExistScheduleJobAsync(TasksQz sysSchedule) { JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); if (await _scheduler.Result.CheckExists(jobKey)) { return true; } else { return false; } } /// /// 暂停一个指定的计划任务 /// /// public async Task> StopScheduleJobAsync(TasksQz sysSchedule) { var result = new MessageModel(); try { JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); if (!await _scheduler.Result.CheckExists(jobKey)) { result.success = false; result.msg = $"未找到要暂停的任务:【{sysSchedule.Name}】"; return result; } else { await this._scheduler.Result.DeleteJob(jobKey); result.success = true; result.msg = $"【{sysSchedule.Name}】成功"; return result; } } catch (Exception) { throw; } } /// /// 恢复指定的计划任务 /// /// /// public async Task> ResumeJob(TasksQz sysSchedule) { var result = new MessageModel(); try { JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); if (!await _scheduler.Result.CheckExists(jobKey)) { result.success = false; result.msg = $"未找到要恢复的任务:【{sysSchedule.Name}】"; return result; } await this._scheduler.Result.ResumeJob(jobKey); result.success = true; result.msg = $"【{sysSchedule.Name}】成功"; return result; } catch (Exception) { throw; } } /// /// 暂停指定的计划任务 /// /// /// public async Task> PauseJob(TasksQz sysSchedule) { var result = new MessageModel(); try { JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); if (!await _scheduler.Result.CheckExists(jobKey)) { result.success = false; result.msg = $"未找到要暂停的任务:【{sysSchedule.Name}】"; return result; } await this._scheduler.Result.PauseJob(jobKey); result.success = true; result.msg = $"【{sysSchedule.Name}】成功"; return result; } catch (Exception) { throw; } } #region 状态状态帮助方法 public async Task> GetTaskStaus(TasksQz sysSchedule) { var ls = new List(); var noTask = new List{ new TaskInfoDto { jobId = sysSchedule.Id.ObjToString(), jobGroup = sysSchedule.JobGroup, triggerId = "", triggerGroup = "", triggerStatus = "不存在" } }; JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); IJobDetail job = await this._scheduler.Result.GetJobDetail(jobKey); if (job == null) { return noTask; } //info.Append(string.Format("任务ID:{0}\r\n任务名称:{1}\r\n", job.Key.Name, job.Description)); var triggers = await this._scheduler.Result.GetTriggersOfJob(jobKey); if (triggers == null || triggers.Count == 0) { return noTask; } foreach (var trigger in triggers) { var triggerStaus = await this._scheduler.Result.GetTriggerState(trigger.Key); string state = GetTriggerState(triggerStaus.ObjToString()); ls.Add(new TaskInfoDto { jobId = job.Key.Name, jobGroup = job.Key.Group, triggerId = trigger.Key.Name, triggerGroup = trigger.Key.Group, triggerStatus = state }); //info.Append(string.Format("触发器ID:{0}\r\n触发器名称:{1}\r\n状态:{2}\r\n", item.Key.Name, item.Description, state)); } return ls; } public string GetTriggerState(string key) { string state = null; if (key != null) key = key.ToUpper(); switch (key) { case "1": state = "暂停"; break; case "2": state = "完成"; break; case "3": state = "出错"; break; case "4": state = "阻塞"; break; case "0": state = "正常"; break; case "-1": state = "不存在"; break; case "BLOCKED": state = "阻塞"; break; case "COMPLETE": state = "完成"; break; case "ERROR": state = "出错"; break; case "NONE": state = "不存在"; break; case "NORMAL": state = "正常"; break; case "PAUSED": state = "暂停"; break; } return state; } #endregion #region 创建触发器帮助方法 /// /// 创建SimpleTrigger触发器(简单触发器) /// /// /// /// /// private ITrigger CreateSimpleTrigger(TasksQz sysSchedule) { if (sysSchedule.CycleRunTimes > 0) { ITrigger trigger = TriggerBuilder.Create() .WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup) .StartAt(sysSchedule.BeginTime.Value) .WithSimpleSchedule(x => x .WithIntervalInSeconds(sysSchedule.IntervalSecond) .WithRepeatCount(sysSchedule.CycleRunTimes - 1)) .EndAt(sysSchedule.EndTime.Value) .Build(); return trigger; } else { ITrigger trigger = TriggerBuilder.Create() .WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup) .StartAt(sysSchedule.BeginTime.Value) .WithSimpleSchedule(x => x .WithIntervalInSeconds(sysSchedule.IntervalSecond) .RepeatForever() ) .EndAt(sysSchedule.EndTime.Value) .Build(); return trigger; } // 触发作业立即运行,然后每10秒重复一次,无限循环 } /// /// 创建类型Cron的触发器 /// /// /// private ITrigger CreateCronTrigger(TasksQz sysSchedule) { // 作业触发器 return TriggerBuilder.Create() .WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup) .StartAt(sysSchedule.BeginTime.Value)//开始时间 .EndAt(sysSchedule.EndTime.Value)//结束数据 .WithCronSchedule(sysSchedule.Cron)//指定cron表达式 .ForJob(sysSchedule.Id.ToString(), sysSchedule.JobGroup)//作业名称 .Build(); } #endregion /// /// 立即执行 一个任务 /// /// /// public async Task> ExecuteJobAsync(TasksQz tasksQz) { var result = new MessageModel(); try { JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup); //判断任务是否存在,存在则 触发一次,不存在则先添加一个任务,触发以后再 停止任务 if (!await _scheduler.Result.CheckExists(jobKey)) { //不存在 则 添加一个计划任务 await AddScheduleJobAsync(tasksQz); //触发执行一次 await _scheduler.Result.TriggerJob(jobKey); //停止任务 await StopScheduleJobAsync(tasksQz); result.success = true; result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功"; } else { var s = _scheduler.Result.GetHashCode(); await _scheduler.Result.TriggerJob(jobKey); //await _scheduler.Result.Shutdown(true); //await _scheduler.Result.Start(); result.success = true; result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功"; } } catch (Exception ex) { result.msg = $"立即执行计划任务失败:【{ex.Message}】"; } return result; } } }