| #region << 版 本 注 释 >> | 
| /*---------------------------------------------------------------- | 
|  * 命名空间:WIDESEAWCS_QuartzJob | 
|  * 创建者:胡童庆 | 
|  * 创建时间:2024/8/2 16:13:36 | 
|  * 版本:V1.0.0 | 
|  * 描述:调度服务实现类 | 
|  * | 
|  * ---------------------------------------------------------------- | 
|  * 修改人: | 
|  * 修改时间: | 
|  * 版本:V1.0.1 | 
|  * 修改说明: | 
|  *  | 
|  *----------------------------------------------------------------*/ | 
| #endregion << 版 本 注 释 >> | 
|   | 
| using Quartz.Impl.Triggers; | 
| using Quartz.Impl; | 
| using Quartz.Spi; | 
| using Quartz; | 
| using System; | 
| using System.Collections.Generic; | 
| using System.Collections.Specialized; | 
| using System.Linq; | 
| using System.Reflection; | 
| using System.Text; | 
| using System.Threading.Tasks; | 
| using WIDESEAWCS_Core; | 
| using WIDESEAWCS_Core.Helper; | 
| using WIDESEAWCS_QuartzJob.DTO; | 
| using WIDESEAWCS_QuartzJob.CustomException; | 
|   | 
| namespace WIDESEAWCS_QuartzJob | 
| { | 
|     public class SchedulerCenterServer : ISchedulerCenter | 
|     { | 
|         private Task<IScheduler> _scheduler; | 
|         private readonly IJobFactory _iocjobFactory; | 
|         public SchedulerCenterServer(IJobFactory jobFactory) | 
|         { | 
|             _iocjobFactory = jobFactory; | 
|             _scheduler = GetSchedulerAsync(); | 
|         } | 
|         private Task<IScheduler> GetSchedulerAsync() | 
|         { | 
|             if (_scheduler != null) | 
|                 return this._scheduler; | 
|             else | 
|             { | 
|                 try | 
|                 { | 
|                     // 从Factory中获取Scheduler实例 | 
|                     NameValueCollection collection = new NameValueCollection | 
|                     { | 
|                         { "quartz.serializer.type", "binary" }, | 
|                     }; | 
|                     StdSchedulerFactory factory = new StdSchedulerFactory(collection); | 
|                     return _scheduler = factory.GetScheduler(); | 
|                 } | 
|                 catch (Exception ex) | 
|                 { | 
|                     throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.JobFactoryInstanceException, ex.Message), innerException: ex); | 
|                 } | 
|   | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 开启任务调度 | 
|         /// </summary> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> StartScheduleAsync() | 
|         { | 
|             WebResponseContent result = new WebResponseContent(); | 
|             try | 
|             { | 
|                 this._scheduler.Result.JobFactory = this._iocjobFactory; | 
|                 if (!this._scheduler.Result.IsStarted) | 
|                 { | 
|                     //等待任务运行完成 | 
|                     await this._scheduler.Result.Start(); | 
|                     await Console.Out.WriteLineAsync(QuartzJobInfoMessage.StartJobSuccess); | 
|                     result = WebResponseContent.Instance.OK(QuartzJobInfoMessage.StartJobSuccess); | 
|                     return result; | 
|                 } | 
|                 else | 
|                 { | 
|                     result = WebResponseContent.Instance.Error(QuartzJobInfoMessage.JobHasStart); | 
|                     return result; | 
|                 } | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.StartJobException, ex.Message), innerException: ex); | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 停止任务调度 | 
|         /// </summary> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> StopScheduleAsync() | 
|         { | 
|             WebResponseContent result = new WebResponseContent(); | 
|             try | 
|             { | 
|                 if (!this._scheduler.Result.IsShutdown) | 
|                 { | 
|                     //等待任务运行完成 | 
|                     await this._scheduler.Result.Shutdown(); | 
|                     await Console.Out.WriteLineAsync(QuartzJobInfoMessage.StopJobSuccess); | 
|                     result = WebResponseContent.Instance.OK(QuartzJobInfoMessage.StopJobSuccess); | 
|                     return result; | 
|                 } | 
|                 else | 
|                 { | 
|                     result = WebResponseContent.Instance.Error(QuartzJobInfoMessage.JobHasStop); | 
|                     return result; | 
|                 } | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.StopJobException, ex.Message), innerException: ex); | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 添加一个计划任务(映射程序集指定IJob实现类) | 
|         /// </summary> | 
|         /// <typeparam name="T"></typeparam> | 
|         /// <param name="tasksQz"></param> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> AddScheduleJobAsync(DispatchInfoDTO tasksQz) | 
|         { | 
|             WebResponseContent result = new WebResponseContent(); | 
|   | 
|             if (tasksQz != null) | 
|             { | 
|                 try | 
|                 { | 
|                     JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup); | 
|                     if (await _scheduler.Result.CheckExists(jobKey)) | 
|                     { | 
|                         result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.JobHasAdd, 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 通过反射获取程序集类型和类    | 
|   | 
|                     var basePath = AppContext.BaseDirectory; | 
|                     var dllFile = Path.Combine(basePath, $"{tasksQz.AssemblyName}.dll"); | 
|   | 
|                     if (!File.Exists(dllFile)) | 
|                     { | 
|                         var msg = $"{tasksQz.AssemblyName}.dll未找到,请检查数据或文件"; | 
|                         //log.Error(msg); | 
|                         throw new Exception(msg); | 
|                     } | 
|   | 
|                     Assembly assembly = Assembly.Load(new AssemblyName(tasksQz.AssemblyName)); | 
|                     Type jobType = assembly.GetType(tasksQz.AssemblyName + "." + tasksQz.ClassName); | 
|   | 
|                     #endregion | 
|   | 
|                     //传入反射出来的执行程序集 | 
|                     //IJobDetail jobDetail = JobBuilder.Create(jobType) | 
|                     //   .WithIdentity(tasksQz.Id.ToString(), tasksQz.JobGroup) | 
|                     //   .Build(); | 
|                     //jobDetail.JobDataMap.Add("JobParams", tasksQz.JobParams); | 
|   | 
|                     IJobDetail job = new JobDetailImpl(tasksQz.Id.ToString(), tasksQz.JobGroup, jobType); | 
|                     job.JobDataMap.Add("JobParams", tasksQz.JobParams); | 
|   | 
|                     ITrigger trigger = CreateSimpleTrigger(tasksQz); | 
|   | 
|                     // 告诉Quartz使用我们的触发器来安排作业 | 
|                     await _scheduler.Result.ScheduleJob(job, trigger); | 
|                     //await _scheduler.Result.ScheduleJob(jobDetail, trigger); | 
|   | 
|                     result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.JobAddSuccess, tasksQz.Name)); | 
|                     return result; | 
|                 } | 
|                 catch (Exception ex) | 
|                 { | 
|                     throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.AddJobException, tasksQz.Name, ex.Message), innerException: ex); | 
|                 } | 
|             } | 
|             else | 
|             { | 
|                 result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.JobNotExist, tasksQz?.Name)); | 
|                 return result; | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 任务是否存在? | 
|         /// </summary> | 
|         /// <returns></returns> | 
|         public async Task<bool> IsExistScheduleJobAsync(DispatchInfoDTO sysSchedule) | 
|         { | 
|             JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); | 
|             if (await _scheduler.Result.CheckExists(jobKey)) | 
|             { | 
|                 return true; | 
|             } | 
|             else | 
|             { | 
|                 return false; | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 停止一个指定的计划任务 | 
|         /// </summary> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> StopScheduleJobAsync(DispatchInfoDTO sysSchedule) | 
|         { | 
|             WebResponseContent result = new WebResponseContent(); | 
|             try | 
|             { | 
|                 JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); | 
|                 if (!await _scheduler.Result.CheckExists(jobKey)) | 
|                 { | 
|                     result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.JobNotExist, sysSchedule.Name)); | 
|                     return result; | 
|                 } | 
|                 else | 
|                 { | 
|                     await this._scheduler.Result.DeleteJob(jobKey); | 
|                     result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.StopAJobSuccess, sysSchedule.Name)); | 
|                     return result; | 
|                 } | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.StopAJobException, sysSchedule.Name, ex.Message), innerException: ex); | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 恢复指定的计划任务 | 
|         /// </summary> | 
|         /// <param name="sysSchedule"></param> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> ResumeJob(DispatchInfoDTO sysSchedule) | 
|         { | 
|             WebResponseContent result = new WebResponseContent(); | 
|             try | 
|             { | 
|                 JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); | 
|                 if (!await _scheduler.Result.CheckExists(jobKey)) | 
|                 { | 
|                     result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.ResumeJobNotExist, sysSchedule.Name)); | 
|                     return result; | 
|                 } | 
|                 await this._scheduler.Result.ResumeJob(jobKey); | 
|                 result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.ResumeJobSuccess, sysSchedule.Name)); | 
|                 return result; | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.ResumeJobException, sysSchedule.Name, ex.Message), innerException: ex); | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 暂停指定的计划任务 | 
|         /// </summary> | 
|         /// <param name="sysSchedule"></param> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> PauseJob(DispatchInfoDTO sysSchedule) | 
|         { | 
|             WebResponseContent result = new WebResponseContent(); | 
|             try | 
|             { | 
|                 JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup); | 
|                 if (!await _scheduler.Result.CheckExists(jobKey)) | 
|                 { | 
|                     result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.PauseJobNotExist, sysSchedule.Name)); | 
|                     return result; | 
|                 } | 
|                 await this._scheduler.Result.PauseJob(jobKey); | 
|                 result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.PauseJobSuccess, sysSchedule.Name)); | 
|                 return result; | 
|             } | 
|             catch (Exception) | 
|             { | 
|                 throw; | 
|             } | 
|         } | 
|   | 
|         #region 状态状态帮助方法 | 
|         //public async Task<List<DispatchInfoDTO>> GetTaskStaus(DispatchInfoDTO sysSchedule) | 
|         //{ | 
|   | 
|         //    var ls = new List<TaskInfoDto>(); | 
|         //    var noTask = new List<TaskInfoDto>{ 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 创建触发器帮助方法 | 
|   | 
|         /// <summary> | 
|         /// 创建SimpleTrigger触发器(简单触发器) | 
|         /// </summary> | 
|         /// <param name="sysSchedule"></param> | 
|         /// <returns></returns> | 
|         private ITrigger CreateSimpleTrigger(DispatchInfoDTO sysSchedule) | 
|         { | 
|             ITrigger trigger = TriggerBuilder.Create() | 
|             .WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup) | 
|             .StartAt(sysSchedule.BeginTime.GetValueOrDefault()) | 
|             .WithSimpleSchedule(x => x | 
|                 .WithIntervalInSeconds(sysSchedule.IntervalSecond) | 
|                 .RepeatForever() | 
|             ) | 
|             .EndAt(sysSchedule.EndTime.GetValueOrDefault()) | 
|             .Build(); | 
|             return trigger; | 
|         } | 
|         #endregion | 
|   | 
|         /// <summary> | 
|         /// 立即执行 一个任务 执行一次 | 
|         /// </summary> | 
|         /// <param name="tasksQz"></param> | 
|         /// <returns></returns> | 
|         public async Task<WebResponseContent> ExecuteJobAsync(DispatchInfoDTO tasksQz) | 
|         { | 
|             var result = new WebResponseContent(); | 
|             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 = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.ExecuteJobSuccess, tasksQz.Name)); | 
|                 } | 
|                 else | 
|                 { | 
|                     await _scheduler.Result.TriggerJob(jobKey); | 
|                     result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.ExecuteJobSuccess, tasksQz.Name)); | 
|                 } | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.ResumeJobException, tasksQz.Name, ex.Message), innerException: ex); | 
|             } | 
|   | 
|             return result; | 
|         } | 
|     } | 
| } |