using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Reflection; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; using Quartz.Impl.Triggers; using Quartz.Spi; using WIDESEA_Common; using WIDESEA_Common.CutomerModel; using WIDESEA_Core.Utilities; using WIDESEA_WCS.WCSClient; namespace WIDESEA_WCS { /// /// 任务调度管理中心 /// public class SchedulerCenterServer : ISchedulerCenterServer { private Task _scheduler; private StdSchedulerFactory _jobFactory; public SchedulerCenterServer(StdSchedulerFactory jobFactory) { _jobFactory = jobFactory; _scheduler = GetSchedulerAsync(); } private Task GetSchedulerAsync() { if (_scheduler != null) return this._scheduler; else { // 从Factory中获取Scheduler实例 NameValueCollection collection = new NameValueCollection { { "quartz.serializer.type", "binary" }, }; StdSchedulerFactory factory = new StdSchedulerFactory(collection); return _scheduler = factory.GetScheduler(); } } #region 将任务计划添加到调度中心 /// /// 添加一个任务 /// /// /// public async Task AddScheduleJobAsync(JobOptions job) { WebResponseContent content = new WebResponseContent(); if (job != null) { try { JobKey jobKey = new JobKey(job.JobName, job.JobGroup); if (!await this._scheduler.Result.CheckExists(jobKey)) { //await Console.Out.WriteLineAsync($"该任务计划已经在执行:【{job.JobName}】,请勿重复启动!"); //content = content.Error($"该任务计划已经在执行:【{job.JobName}】,请勿重复启动!"); //return content; #region 设置开始时间和结束时间 if (job.BeginTime == null) { job.BeginTime = DateTime.Now; } DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(job.BeginTime, 1);//设置开始时间 if (job.EndTime == null) { job.EndTime = DateTime.MaxValue.AddDays(-1); } DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(job.EndTime, 1);//设置暂停时间 #endregion Assembly assembly = Assembly.Load(new AssemblyName(job.AssemblyName)); Type jobType = assembly.GetType(job.AssemblyName + "." + job.ClassName); //判断任务调度是否已经开启 //if (!this._scheduler.Result.IsStarted) //{ // await StartScheduleAsync(); //} //传入反射出来的执行程序集 IJobDetail jobDetail = new JobDetailImpl(job.JobName, job.JobGroup, jobType); jobDetail.JobDataMap.Add("JobParams", job.JobParams); ITrigger trigger; if (job.Cron != null && CronExpression.IsValidExpression(job.Cron) && job.TriggerType > 0) { trigger = CreateCronTrigger(job); ((CronTriggerImpl)trigger).MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing; } else { trigger = CreateSimpleTrigger(job); } // 告诉Quartz使用我们的触发器来安排作业 await _scheduler.Result.ScheduleJob(jobDetail, trigger); } await Console.Out.WriteLineAsync($"【{job.JobName}】任务计划添加成功"); return content = content.OK(message: $"【{job.JobName}】添加成功"); } catch (Exception ex) { Console.Out.WriteLine($"任务计划异常:【{ex.Message}】"); //this._scheduler.Dispose(); this._scheduler = null; return content = content.Error(message: $"任务计划异常:【{ex.Message}】"); } } else { await Console.Out.WriteLineAsync($"任务计划不存在:【{job?.JobName}】"); content = content.Error($"任务计划不存在:【{job?.JobName}】"); } return content; } #endregion #region 检测任务是否存在 /// /// 检测任务是否存在 /// /// /// public async Task IsExistScheduleJobAsync(JobOptions job) { JobKey jobKey = new JobKey(job.JobName, job.JobGroup); if (await _scheduler.Result.CheckExists(jobKey)) { return true; } else { return false; } } #endregion #region 暂停指定的计划任务 /// /// 暂停指定的计划任务 /// /// /// public async Task PauseJob(JobOptions job) { WebResponseContent content = new WebResponseContent(); try { JobKey jobKey = new JobKey(job.JobName, job.JobGroup); if (!await _scheduler.Result.CheckExists(jobKey)) { await Console.Out.WriteLineAsync($"未找到要暂停的任务:【{job.JobName}】"); content = content.Error($"未找到要暂停的任务:【{job.JobName}】"); return content; } await this._scheduler.Result.PauseJob(jobKey); await Console.Out.WriteLineAsync($"【{job.JobName}】任务计划暂停成功"); content = content.OK($"【{job.JobName}】暂停成功"); return content; } catch (Exception ex) { await Console.Out.WriteLineAsync($"【{job.JobName}】暂停任务异常:【{ex.Message}】"); content = content.Error($"【{job.JobName}】暂停任务异常:【{ex.Message}】"); return content; } } #endregion #region 恢复一个指定的任务 /// /// 恢复一个指定的任务 /// /// /// public async Task ResumeJob(JobOptions job) { WebResponseContent content = new WebResponseContent(); try { JobKey jobKey = new JobKey(job.JobName, job.JobGroup); if (!await _scheduler.Result.CheckExists(jobKey)) { await Console.Out.WriteLineAsync($"未找到要恢复的任务:【{job.JobName}】"); content = content.Error($"未找到要恢复的任务:【{job.JobName}】"); return content; } await this._scheduler.Result.ResumeJob(jobKey); await Console.Out.WriteLineAsync($"【{job.JobName}】任务计划恢复成功"); content = content.OK($"【{job.JobName}】恢复成功"); return content; } catch (Exception ex) { await Console.Out.WriteLineAsync($"恢复任务【{job.JobName}】异常:【{ex.Message}】"); content = content.Error($"恢复任务异常:【{ex.Message}】"); return content; } } #endregion #region 开启任务调度 /// /// 开启任务调度 /// /// public async Task StartScheduleAsync() { WebResponseContent content = new WebResponseContent(); try { if (!this._scheduler.Result.IsStarted) { await this._scheduler.Result.Start(); await Console.Out.WriteLineAsync("任务调度开启!"); content = content.OK(message: $"任务调度开启成功"); } else { await Console.Out.WriteLineAsync($"任务调度已经开启"); content = content.Error($"任务调度已经开启"); } } catch (Exception ex) { await Console.Out.WriteLineAsync($"任务调度开启异常:{ex.Message}"); content = content.Error($"任务调度开启异常:{ex.Message}"); } return content; } #endregion #region 停止调度中心任务调度 /// /// 停止调度中心任务调度 /// /// public async Task StopScheduleAsync() { WebResponseContent content = new WebResponseContent(); try { if (!this._scheduler.Result.IsShutdown) { await this._scheduler.Result.Shutdown(); await Console.Out.WriteLineAsync("任务调度停止!"); content = content.OK(message: $"任务调度停止成功"); } else { await Console.Out.WriteLineAsync($"任务调度已经停止"); content = content.Error(message: $"任务调度已经停止"); } } catch (Exception ex) { await Console.Out.WriteLineAsync($"任务调度停止异常:+{ex.Message}"); content = content.Error(message: $"任务调度停止异常:+{ex.Message}"); } return content; } #endregion #region 停止一个指定的任务计划 /// /// 停止一个指定的任务计划 /// /// /// public async Task StopScheduleJobAsync(JobOptions job) { WebResponseContent content = new WebResponseContent(); try { JobKey jobKey = new JobKey(job.JobName, job.JobGroup); if (!await _scheduler.Result.CheckExists(jobKey)) { await Console.Out.WriteLineAsync($"未找到要暂停的任务:【{ job.JobName}】"); content = content.Error(message: $"未找到要暂停的任务:【{ job.JobName}】"); } else { await this._scheduler.Result.DeleteJob(jobKey); await Console.Out.WriteLineAsync($"【{job.JobName}】任务计划暂停成功"); content = content.OK(message: $"【{job.JobName}】暂停成功"); } } catch (Exception ex) { await Console.Out.WriteLineAsync($"【{job.JobName}】任务计划暂停异常:【{ ex.Message}】"); content = content.Error(message: $"暂停任务异常:【{ ex.Message}】"); } return content; } #endregion #region 状态状态帮助方法 public async Task> GetTaskStaus(JobOptions jobOptions) { var ls = new List(); var noTask = new List{ new TaskInfoDto { JobId = jobOptions.JobName.ObjToString(), JobGroup = jobOptions.JobGroup, TriggerId = "", TriggerGroup = "", TriggerStatus = "不存在", PLCConnetState = jobOptions.PLCConnectState } }; JobKey jobKey = new JobKey(jobOptions.JobName.ToString(), jobOptions.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, PLCConnetState = jobOptions.PLCConnectState }); //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(JobOptions job) { if (job.CycleRunTimes > 0) { ITrigger trigger = TriggerBuilder.Create() .WithIdentity(job.JobName, job.JobGroup) .StartAt(job.BeginTime.Value) .WithSimpleSchedule(x => x .WithIntervalInSeconds(job.IntervalSecond) .WithRepeatCount(job.CycleRunTimes - 1)) .EndAt(job.EndTime.Value) .Build(); return trigger; } else { ITrigger trigger = TriggerBuilder.Create() .WithIdentity(job.JobName, job.JobGroup) .StartAt(job.BeginTime.Value) .WithSimpleSchedule(x => x .WithIntervalInSeconds(job.IntervalSecond) .RepeatForever() ) .EndAt(job.EndTime.Value) .Build(); return trigger; } } /// /// 创建类型Cron的触发器 /// /// /// private ITrigger CreateCronTrigger(JobOptions job) { // 作业触发器 return TriggerBuilder.Create() .WithIdentity(job.JobName, job.JobGroup) .StartAt(job.BeginTime.Value)//开始时间 .EndAt(job.EndTime.Value)//结束数据 .WithCronSchedule(job.Cron)//指定cron表达式 .ForJob(job.JobName, job.JobGroup)//作业名称 .Build(); } #endregion #region 立即执行 一个任务 /// /// 立即执行 一个任务 /// /// /// public async Task ExecuteJobAsync(JobOptions job) { WebResponseContent result = new WebResponseContent(); try { JobKey jobKey = new JobKey(job.JobName.ToString(), job.JobGroup); //判断任务是否存在,存在则 触发一次,不存在则先添加一个任务,触发以后再 停止任务 if (!await _scheduler.Result.CheckExists(jobKey)) { //不存在 则 添加一个计划任务 await AddScheduleJobAsync(job); //触发执行一次 await _scheduler.Result.TriggerJob(jobKey); //停止任务 await StopScheduleJobAsync(job); result.Status = true; result.Message = $"立即执行计划任务:【{job.JobName}】成功"; } else { await _scheduler.Result.TriggerJob(jobKey); result.Status = true; result.Message = $"立即执行计划任务:【{job.JobName}】成功"; } } catch (Exception ex) { result.Message = $"立即执行计划任务失败:【{ex.Message}】"; } return result; } public void Dispose() { throw new NotImplementedException(); } #endregion } }