QuartzHelper.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. using System;
  2. using System.Collections.Generic;
  3. using log4net;
  4. using Quartz;
  5. using Quartz.Impl;
  6. using Quartz.Impl.Matchers;
  7. namespace ShwasherSys.QuartzHelpers
  8. {
  9. public class QuartzHelper
  10. {
  11. public static QuartzHelper Instance { get; set; } = new QuartzHelper();
  12. #region Field Properties
  13. private readonly ILog _log = LogManager.GetLogger(typeof(QuartzHelper));
  14. public ISchedulerFactory SchedulerFactory { get; set; }
  15. public IScheduler Sched { get; set; }
  16. public string JobName { get; set; }
  17. public string JobGroupName { get; set; }
  18. public string TriggerName { get; set; }
  19. public string TriggerGroupName { get; set; }
  20. public IJobDetail JobDetail { get; set; }
  21. public ITrigger Trigger { get; set; }
  22. DateTimeOffset? TimeOffset { get; set; }
  23. public string ErrorMsg { get; set; }
  24. //public ICronTrigger CronTrigger { get; set; }
  25. //public ISimpleTrigger SimpleTrigger { get; set; }
  26. #endregion
  27. #region Initialize
  28. private IScheduler GetScheduler()
  29. {
  30. IScheduler scheduler = null;
  31. try
  32. {
  33. scheduler = SchedulerFactory.GetScheduler().Result;
  34. }
  35. catch (SchedulerException e)
  36. {
  37. LogManager.GetLogger(typeof(QuartzHelper)).Info(e.Message);
  38. }
  39. return scheduler;
  40. }
  41. public QuartzHelper()
  42. {
  43. SchedulerFactory = new StdSchedulerFactory();
  44. Sched = GetScheduler();
  45. }
  46. public QuartzHelper(string jobName, string jobGroupName) : this()
  47. {
  48. TriggerName = JobName = jobName;
  49. JobGroupName = JobGroupName = jobGroupName;
  50. }
  51. public QuartzHelper(string jobName, string jobGroupName, string triggerName, string triggerGroupName) : this(jobName, jobGroupName)
  52. {
  53. TriggerName = triggerName;
  54. JobGroupName = triggerGroupName;
  55. }
  56. public QuartzHelper(string jobName, string jobGroupName, IJobDetail jobDetail, ITrigger trigger) : this(jobName, jobGroupName)
  57. {
  58. JobDetail = jobDetail;
  59. Trigger = trigger;
  60. }
  61. public QuartzHelper(IJobDetail jobDetail, ITrigger trigger)
  62. {
  63. SchedulerFactory = new StdSchedulerFactory();
  64. Sched = SchedulerFactory.GetScheduler().Result;
  65. JobDetail = jobDetail;
  66. Trigger = trigger;
  67. }
  68. #endregion
  69. #region Create JobDetail
  70. /// <summary>
  71. /// 向Scheduler(调度程序)中添加Job
  72. /// </summary>
  73. /// <returns></returns>
  74. public bool CreateJob()
  75. {
  76. if (JobDetail != null && Trigger != null)
  77. {
  78. if (Sched.IsShutdown)
  79. {
  80. SchedulerFactory = new StdSchedulerFactory();
  81. Sched = SchedulerFactory.GetScheduler().Result;
  82. }
  83. if (CheckJobIsExist(JobDetail))
  84. ErrorMsg = "JobtType:" + JobDetail.Key + " 已存在!";
  85. TimeOffset = Sched.ScheduleJob(JobDetail, Trigger).Result;
  86. _log.Info("[" + JobDetail.Key + "] will run at: " + TimeOffset + "---->");
  87. return true;
  88. }
  89. return false;
  90. }
  91. /// <summary>
  92. /// 向Scheduler(调度程序)中添加Job
  93. /// </summary>
  94. /// <param name="jobDetail"></param>
  95. /// <param name="trigger"></param>
  96. /// <returns></returns>
  97. public bool CreateJob(IJobDetail jobDetail, ITrigger trigger)
  98. {
  99. ErrorMsg = "";
  100. if (jobDetail != null && trigger != null)
  101. {
  102. if (Sched.IsShutdown)
  103. {
  104. SchedulerFactory = new StdSchedulerFactory();
  105. Sched = SchedulerFactory.GetScheduler().Result;
  106. }
  107. if (CheckJobIsExist(jobDetail))
  108. ErrorMsg = "JobtType:[" + jobDetail.Key + "] Is Exist!";
  109. else
  110. {
  111. try
  112. {
  113. TimeOffset = Sched.ScheduleJob(jobDetail, trigger).Result;
  114. _log.Info("JobtType:[" + jobDetail.Key + "] will run at: " + TimeOffset + "---->");
  115. return true;
  116. }
  117. catch (Exception e)
  118. {
  119. _log.Error(e.Message);
  120. ErrorMsg = "System Error!";
  121. }
  122. }
  123. }
  124. else
  125. {
  126. ErrorMsg = "JobDetail/Trigger is null";
  127. }
  128. return false;
  129. }
  130. /// <summary>
  131. /// 向Scheduler(调度程序)中添加Job
  132. /// </summary>
  133. /// <param name="jobType"></param>
  134. /// <param name="trigger"></param>
  135. /// <param name="jobName"></param>
  136. /// <param name="jobGroupName"></param>
  137. /// <returns></returns>
  138. public bool CreateJob(Type jobType, ITrigger trigger, string jobName = null, string jobGroupName = null)
  139. {
  140. IJobDetail jobDetail = GetJobDetail(jobType, jobName, jobGroupName);
  141. if (jobDetail == null)
  142. return false;
  143. return CreateJob(jobDetail, trigger);
  144. }
  145. /// <summary>
  146. /// 向Scheduler(调度程序)中添加Job
  147. /// </summary>
  148. /// <param name="jobType"></param>
  149. /// <param name="triggerStr">
  150. /// 触发器参数:【"开始时间"|"开始时间单位(参照IntervalUnit)"|"间隔时间"|"间隔时间单位(参照IntervalUnit)"|"重复次数(0代表无限循环)"】
  151. /// 【"cronExpStr"】(特定时间执行,填*代表每年每月...,填具体值代表特定值(多个值,间隔、范围值用-,a/b 指 从a开始,每隔b 触发一次))
  152. /// </param>
  153. /// <param name="triggerType">触发器类型</param>
  154. /// <param name="jobName"></param>
  155. /// <param name="jobGroupName"></param>
  156. /// <returns></returns>
  157. public bool CreateJob(Type jobType, string triggerStr, TriggerType triggerType = TriggerType.SimpleTrigger, string jobName = null, string jobGroupName = null)
  158. {
  159. IJobDetail jobDetail = GetJobDetail(jobType, jobName, jobGroupName);
  160. if (jobDetail == null)
  161. return false;
  162. ITrigger trigger;
  163. switch (triggerType)
  164. {
  165. #region SimpleTrigger
  166. case TriggerType.SimpleTrigger:
  167. if (GetSimpleTrigger(triggerStr, out trigger))
  168. return CreateJob(jobDetail, trigger);
  169. break;
  170. #endregion
  171. #region CronTrigger
  172. case TriggerType.CronTrigger:
  173. string cronExpStr = triggerStr;
  174. //if (!string.IsNullOrEmpty(triggerArr[0]))
  175. // cronExpStr = GetCronExpString(triggerArr[0]);
  176. //else if (triggerArr.Length == 2)
  177. // cronExpStr = triggerArr[1];
  178. if (GetCronTrigger(cronExpStr, out trigger))
  179. return CreateJob(jobDetail, trigger);
  180. break;
  181. #endregion
  182. }
  183. return false;
  184. }
  185. /// <summary>
  186. /// 向Scheduler(调度程序)中添加Job
  187. /// </summary>
  188. /// <param name="jobType"></param>
  189. /// <param name="cronExpStr">CronSchedule 触发器表达式</param>
  190. /// <param name="jobName"></param>
  191. /// <param name="jobGroupName"></param>
  192. /// <returns></returns>
  193. public bool CreateJob(Type jobType, string cronExpStr, string jobName = null, string jobGroupName = null)
  194. {
  195. IJobDetail jobDetail = GetJobDetail(jobType, jobName, jobGroupName);
  196. if (jobDetail == null)
  197. return false;
  198. ITrigger trigger;
  199. if (GetCronTrigger(cronExpStr, out trigger))
  200. return CreateJob(jobDetail, trigger);
  201. return false;
  202. }
  203. /// <summary>
  204. /// 向Scheduler(调度程序)中添加多个job任务
  205. /// </summary>
  206. /// <param name="triggersAndJobs"></param>
  207. /// <param name="replace"></param>
  208. public void CreateJobs(IReadOnlyDictionary<IJobDetail, IReadOnlyCollection<ITrigger>> triggersAndJobs, bool replace)
  209. {
  210. Sched.ScheduleJobs(triggersAndJobs, replace);
  211. }
  212. /// <summary>
  213. /// 添加 JobDetail
  214. /// </summary>
  215. /// <param name="jobdetail"></param>
  216. /// <param name="replace">是否覆盖</param>
  217. public void AddJob(IJobDetail jobdetail, bool replace)
  218. {
  219. Sched.AddJob(jobdetail, replace);
  220. }
  221. #endregion
  222. #region Get JobDetail
  223. /// <summary>
  224. /// 获取 JobDetail
  225. /// </summary>
  226. /// <param name="key"></param>
  227. /// <returns></returns>
  228. public IJobDetail GetJobDetail(JobKey key)
  229. {
  230. return CheckJobIsExist(key) ? Sched.GetJobDetail(key).Result : null;
  231. }
  232. /// <summary>
  233. /// 获取 JobDetail
  234. /// </summary>
  235. /// <param name="jobName"></param>
  236. /// <param name="jobGroupName"></param>
  237. /// <returns></returns>
  238. public IJobDetail GetJobDetail(string jobName, string jobGroupName)
  239. {
  240. JobKey key = GetJobKey(jobName, jobGroupName);
  241. return GetJobDetail(key);
  242. }
  243. /// <summary>
  244. /// 构造 JobDetail
  245. /// </summary>
  246. /// <param name="jobType"></param>
  247. /// <param name="jobName"></param>
  248. /// <param name="jobGroupName"></param>
  249. /// <returns></returns>
  250. public IJobDetail GetJobDetail(Type jobType, string jobName = null, string jobGroupName = null)
  251. {
  252. jobName = jobName ?? JobName;
  253. jobGroupName = jobGroupName ?? JobGroupName;
  254. if (string.IsNullOrEmpty(jobName) || string.IsNullOrEmpty(jobGroupName))
  255. {
  256. ErrorMsg = "jobName/jobGroupName is empty!";
  257. return null;
  258. }
  259. IJobDetail jobDetail = null;
  260. try
  261. {
  262. jobDetail = new JobDetailImpl(jobName, jobGroupName, jobType);
  263. }
  264. catch (Exception e)
  265. {
  266. _log.Error(e.Message);
  267. ErrorMsg = e.Message;
  268. }
  269. return jobDetail;
  270. }
  271. /// <summary>
  272. /// 获取job 组名
  273. /// </summary>
  274. /// <returns></returns>
  275. public IReadOnlyCollection<string> GetJobGroupNames()
  276. {
  277. return Sched.GetJobGroupNames().Result;
  278. }
  279. /// <summary>
  280. /// 给JobDetail设置参数
  281. /// </summary>
  282. /// <param name="jobDetail"></param>
  283. /// <param name="parmDic">参数的值</param>
  284. /// <param name="parmKey">参数的键</param>
  285. public void SetJobDetailParm(IJobDetail jobDetail, Dictionary<string, object> parmDic, string parmKey = "jobParm")
  286. {
  287. var map = jobDetail.JobDataMap.Get(parmKey);
  288. if (map != null)
  289. {
  290. jobDetail.JobDataMap[parmKey] = parmDic;
  291. }
  292. else
  293. {
  294. jobDetail.JobDataMap.Put(parmKey, parmDic);
  295. }
  296. }
  297. #endregion
  298. #region Delete JobDetail
  299. public bool DeleteJob(string jobName = null, string jobGroupName = null)
  300. {
  301. jobName = jobName ?? JobName;
  302. jobGroupName = jobGroupName ?? JobGroupName;
  303. return DeleteJob(GetJobKey(jobName, jobGroupName));
  304. }
  305. public bool DeleteJob(IJobDetail jobDetail)
  306. {
  307. return jobDetail != null && Sched.DeleteJob(jobDetail.Key).Result;
  308. }
  309. public bool DeleteJob(JobKey key)
  310. {
  311. return Sched.DeleteJob(key).Result;
  312. }
  313. public bool DeleteJobs(string jobGroupName = null)
  314. {
  315. jobGroupName = jobGroupName ?? JobGroupName;
  316. var keys = GetJobKeys(jobGroupName);
  317. return Sched.DeleteJobs(keys).Result;
  318. }
  319. public bool DeleteJobs(List<JobKey> keys)
  320. {
  321. return Sched.DeleteJobs(keys).Result;
  322. }
  323. /*
  324. * 首先从Scheduler.scheduleJob(JobDetail jobDetail, Trigger trigger) 调度job,实际上就是将job存储到RAM中的jobsByGroup,jobsByKey对应的Map中, 将trigger存储到triggers(List),triggersByKey,triggersByGroup对应的Map中,及timeTriggers的Treeset中。
  325. * Scheduler.unscheduleJob(TriggerKey triggerKey) 就是将triggerKey从triggersByKey,triggersByGroup,triggers,timeTriggers中移除;
  326. * Scheduler.deleteJob(JobKey jobKey)除了从容器triggers中的TriggerWrapper的JobKey为jobKey的List<TriggerWrapper>,并unscheduleJob(TriggerKey triggerKey)列表 List<TriggerWrapper>中的所有TriggerWrapper,同时从jobsByKey,jobsByGroup的移除对应jobKey的相关信息
  327. */
  328. /// <summary>
  329. /// 停止调度Job任务
  330. /// </summary>
  331. /// <param name="triggerkey"></param>
  332. /// <returns></returns>
  333. /// <para>If the related job does not have any other triggers, and the job is
  334. /// not durable, then the job will also be deleted.</para>
  335. public bool UnscheduleJob(TriggerKey triggerkey)
  336. {
  337. return Sched.UnscheduleJob(triggerkey).Result;
  338. }
  339. /// <summary>
  340. /// 停止多个调度Job任务
  341. /// </summary>
  342. /// <param name="triggerkeys"></param>
  343. /// <returns></returns>
  344. public bool UnscheduleJobs(List<TriggerKey> triggerkeys)
  345. {
  346. return Sched.UnscheduleJobs(triggerkeys).Result;
  347. }
  348. /// <summary>
  349. /// 重新恢复触发器相关的job任务
  350. /// </summary>
  351. /// <param name="triggerkey"></param>
  352. /// <param name="trigger"></param>
  353. /// <returns></returns>
  354. public DateTimeOffset? RescheduleJob(TriggerKey triggerkey, ITrigger trigger)
  355. {
  356. return Sched.RescheduleJob(triggerkey, trigger).Result;
  357. }
  358. #endregion
  359. #region Get Trigger
  360. public ITrigger GetTrigger(TriggerKey key)
  361. {
  362. return CheckTriggerIsExist(key) ? Sched.GetTrigger(key).Result : null;
  363. }
  364. public ITrigger GetTrigger(string triggerName, string triggerGroupName)
  365. {
  366. var key = GetTriggerKey(triggerName, triggerGroupName);
  367. return GetTrigger(key);
  368. }
  369. /// <summary>
  370. /// 获取 指定 Job 里的所有 Trigger
  371. /// </summary>
  372. /// <param name="key"></param>
  373. /// <returns></returns>
  374. public IReadOnlyCollection<ITrigger> GetTriggersByJob(JobKey key)
  375. {
  376. return CheckJobIsExist(key) ? Sched.GetTriggersOfJob(key).Result : null;
  377. }
  378. /// <summary>
  379. /// 获取 指定 TriggerGroup 里的所有 Trigger
  380. /// </summary>
  381. /// <param name="triggerGroupName"></param>
  382. /// <returns></returns>
  383. public IList<ITrigger> GetTriggersByGroup(string triggerGroupName)
  384. {
  385. IList<ITrigger> triggerList = new List<ITrigger>();
  386. var keys = GetTriggerKeys(triggerGroupName);
  387. foreach (var triggerKey in keys)
  388. {
  389. triggerList.Add(GetTrigger(triggerKey));
  390. }
  391. return triggerList;
  392. }
  393. /// <summary>
  394. /// 获取所有的 Trigger
  395. /// </summary>
  396. /// <returns></returns>
  397. public IList<ITrigger> GetTriggers()
  398. {
  399. List<ITrigger> triggerList = new List<ITrigger>();
  400. var triggerGroupNames = GetTriggerGroupNames();
  401. foreach (var name in triggerGroupNames)
  402. {
  403. triggerList.AddRange(GetTriggersByGroup(name));
  404. }
  405. return triggerList;
  406. }
  407. /// <summary>
  408. /// 获取暂停的 Trigger
  409. /// </summary>
  410. /// <returns></returns>
  411. public IList<ITrigger> GetPausedTriggers()
  412. {
  413. List<ITrigger> triggerList = new List<ITrigger>();
  414. var triggerGroupNames = GetPausedTriggerGroupNames();
  415. foreach (var name in triggerGroupNames)
  416. {
  417. triggerList.AddRange(GetTriggersByGroup(name));
  418. }
  419. return triggerList;
  420. }
  421. /// <summary>
  422. /// 获取 所有的 TriggerGroupName
  423. /// </summary>
  424. /// <returns></returns>
  425. public IReadOnlyCollection<string> GetTriggerGroupNames()
  426. {
  427. return Sched.GetTriggerGroupNames().Result;
  428. }
  429. /// <summary>
  430. /// 获取 暂停的 TriggerGroupName
  431. /// </summary>
  432. /// <returns></returns>
  433. public IReadOnlyCollection<string> GetPausedTriggerGroupNames()
  434. {
  435. return Sched.GetPausedTriggerGroups().Result;
  436. }
  437. /// <summary>
  438. /// 获取 指定 Trigger 的 TriggerState
  439. /// </summary>
  440. /// <param name="key"></param>
  441. /// <returns></returns>
  442. public TriggerState GetTriggerState(TriggerKey key)
  443. {
  444. return CheckTriggerIsExist(key) ? Sched.GetTriggerState(key).Result : TriggerState.None;
  445. }
  446. /// <summary>
  447. /// 根据参数数组(1个|4个)创建SimpleTrigger
  448. /// </summary>
  449. /// <param name="triggerStr"></param>
  450. /// <param name="trigger"></param>
  451. /// <param name="triggerName"></param>
  452. /// <param name="triggerGroupName"></param>
  453. /// <returns></returns>
  454. public bool GetSimpleTrigger(string triggerStr, out ITrigger trigger, string triggerName = null, string triggerGroupName = null)
  455. {
  456. trigger = null;
  457. if (string.IsNullOrEmpty(triggerName)) triggerName = TriggerName;
  458. if (string.IsNullOrEmpty(triggerGroupName)) triggerGroupName = TriggerName;
  459. if (CheckTriggerIsExist(triggerName, triggerGroupName))
  460. {
  461. ErrorMsg = "Trigger[" + triggerGroupName + "." + triggerName + "] Is Exist";
  462. return false;
  463. }
  464. string[] triggerArr = triggerStr.Split('|');
  465. #region Length = 1
  466. if (triggerArr.Length == 1)
  467. {
  468. ErrorMsg = "参数 [1]TriggerArray 有误,不能解析。";
  469. DateTimeOffset startTime;
  470. if (!DateTimeOffset.TryParse(triggerArr[0], out startTime)) return false;
  471. //int start, startUnit;
  472. //if (!int.TryParse(triggerArr[0], out start)) return false;
  473. //if (!int.TryParse(triggerArr[1], out startUnit)) return false;
  474. //DateTimeOffset startTime = DateBuilder.FutureDate(start, (IntervalUnit)startUnit);
  475. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  476. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime).Build();
  477. _log.InfoFormat("Trigger----{0}----{1}----", triggerArr[0], triggerArr[1]);
  478. ErrorMsg = "";
  479. return true;
  480. }
  481. #endregion
  482. #region Length = 4
  483. if (triggerArr.Length == 4)
  484. {
  485. ErrorMsg = "参数 [4]TriggerArray 有误,不能解析。";
  486. DateTimeOffset startTime;
  487. int interval, intervalUnit, repeatCount;
  488. if (!DateTimeOffset.TryParse(triggerArr[0], out startTime)) return false;
  489. if (!int.TryParse(triggerArr[1], out interval)) return false;
  490. if (!int.TryParse(triggerArr[2], out intervalUnit)) return false;
  491. // = DateBuilder.FutureDate(future, (IntervalUnit)futureUnit);
  492. if (string.IsNullOrEmpty(triggerArr[3]))
  493. repeatCount = 0;
  494. else if (!int.TryParse(triggerArr[3], out repeatCount)) return false;
  495. switch (repeatCount)
  496. {
  497. case 0:
  498. switch (intervalUnit)
  499. {
  500. default:
  501. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  502. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  503. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).RepeatForever()).Build();
  504. break;
  505. case 1:
  506. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  507. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  508. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).RepeatForever()).Build();
  509. break;
  510. case 2:
  511. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  512. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  513. .WithSimpleSchedule(x => x.WithIntervalInMinutes(interval).RepeatForever()).Build();
  514. break;
  515. case 3:
  516. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  517. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  518. .WithSimpleSchedule(x => x.WithIntervalInHours(interval).RepeatForever()).Build();
  519. break;
  520. }
  521. break;
  522. default:
  523. repeatCount = repeatCount - 1;
  524. switch (intervalUnit)
  525. {
  526. default:
  527. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  528. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  529. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).WithRepeatCount(repeatCount)).Build();
  530. break;
  531. case 1:
  532. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  533. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  534. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).WithRepeatCount(repeatCount)).Build();
  535. break;
  536. case 2:
  537. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  538. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  539. .WithSimpleSchedule(x => x.WithIntervalInMinutes(interval).WithRepeatCount(repeatCount)).Build();
  540. break;
  541. case 3:
  542. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  543. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  544. .WithSimpleSchedule(x => x.WithIntervalInHours(interval).WithRepeatCount(repeatCount)).Build();
  545. break;
  546. }
  547. break;
  548. }
  549. _log.InfoFormat("Trigger----{0}----{1}----{2}----{3}----", triggerArr[0], triggerArr[1], triggerArr[2],
  550. triggerArr[3]);
  551. ErrorMsg = "";
  552. return true;
  553. }
  554. #endregion
  555. ErrorMsg = "参数 TriggerArray 有误,不能解析。";
  556. return false;
  557. }
  558. /// <summary>
  559. /// 根据表达式创建CronTrigger
  560. /// </summary>
  561. /// <param name="cronExpStr"></param>
  562. /// <param name="trigger"></param>
  563. /// <param name="triggerName"></param>
  564. /// <param name="triggerGroupName"></param>
  565. /// <returns></returns>
  566. public bool GetCronTrigger(string cronExpStr, out ITrigger trigger, string triggerName = null, string triggerGroupName = null)
  567. {
  568. trigger = null;
  569. if (string.IsNullOrEmpty(triggerName)) triggerName = TriggerName;
  570. if (string.IsNullOrEmpty(triggerGroupName)) triggerGroupName = TriggerName;
  571. if (CheckTriggerIsExist(triggerName, triggerGroupName))
  572. {
  573. ErrorMsg = "Trigger[" + triggerGroupName + "." + triggerName + "] Is Exist";
  574. return false;
  575. }
  576. try
  577. {
  578. trigger = (ICronTrigger)TriggerBuilder.Create()
  579. .WithIdentity(triggerName, triggerGroupName).WithCronSchedule(cronExpStr).Build();
  580. return true;
  581. }
  582. catch (Exception e)
  583. {
  584. _log.Error(e.Message);
  585. ErrorMsg = e.Message;
  586. }
  587. return false;
  588. }
  589. /// <summary>
  590. /// 根据参数 创建 Cron表达式
  591. /// </summary>
  592. /// <param name="triggerStr">["*y*M*d*H*m*s"]</param>
  593. /// <returns></returns>
  594. public string GetCronExpString(string triggerStr)
  595. {
  596. try
  597. {
  598. int s = triggerStr.IndexOf("s", StringComparison.Ordinal);
  599. int e = triggerStr.IndexOf("m", StringComparison.Ordinal) + 1;
  600. string sec = ConvertSpaceStr(triggerStr.Substring(e, s - e));
  601. s = e - 1;
  602. e = triggerStr.IndexOf("H", StringComparison.Ordinal) + 1;
  603. string min = ConvertSpaceStr(triggerStr.Substring(e, s - e));
  604. s = e - 1;
  605. e = triggerStr.IndexOf("d", StringComparison.Ordinal) + 1;
  606. string hour = ConvertSpaceStr(triggerStr.Substring(e, s - e));
  607. s = e - 1;
  608. e = triggerStr.IndexOf("M", StringComparison.Ordinal) + 1;
  609. string day = ConvertSpaceStr(triggerStr.Substring(e, s - e));
  610. s = e - 1;
  611. e = triggerStr.IndexOf("y", StringComparison.Ordinal) + 1;
  612. string month = ConvertSpaceStr(triggerStr.Substring(e, s - e));
  613. s = e - 1;
  614. e = 0;
  615. string year = ConvertSpaceStr(triggerStr.Substring(e, s - e));
  616. var ss = sec + " " + min + " " + hour + " " + day + " " + month + " ? " + year + "";
  617. return ss;
  618. }
  619. catch (Exception exception)
  620. {
  621. _log.Error(exception);
  622. }
  623. return "";
  624. /*****cron表达式说明
  625. * 六个或七个单元
  626. * 秒 分 时 月中天 月份 月中星期几 (年)
  627. * 秒,分,时,天
  628. * 字段 允许值 允许的特殊字符
  629. 秒 0-59 , - * /
  630. 分 0-59 , - * /
  631. 小时 0-23 , - * /
  632. 日期 1-31 , - * ? / L W C
  633. 月份 1-12 或者 JAN-DEC , - * /
  634. 星期 1-7 或者 SUN-SAT , - * ? / L C #
  635. 年(可选) 留空, 1970-2099 , - * /
  636. ----> 符号说明
  637. *:表示任意时刻
  638. ?:只能在日或周字段上使用,简单的理解就是日期和星期是有冲突的,指定其中一个的话,另外一个是没办法指定的,比如每个月12号和每个星期二,这两个是"互斥"的,不能用日期和周来指定所有“每个是星期二的12号”这个时间。
  639. -:范围,如 1-5秒
  640. ,:列表,如 1,5,10 秒
  641. /:等步长序列,如3/13秒 表示 3,16,29,42,55,3,16...
  642. L:仅在日和周上支持,表示允许的最后一个值,注意不要让范围和列表与L连用
  643. W:工作日
  644. #:为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。
  645. *****/
  646. //秒 分 时 月中天 月份 月中星期几 (年)
  647. }
  648. /// <summary>
  649. /// 根据参数 创建 Cron表达式
  650. /// </summary>
  651. /// <param name="triggerArr"></param>
  652. /// <returns></returns>
  653. public string GetCronExpString(string[] triggerArr)
  654. {
  655. if (triggerArr.Length != 6)
  656. return "";
  657. return ConvertSpaceStr(triggerArr[5]) + " " + ConvertSpaceStr(triggerArr[4]) + " " + ConvertSpaceStr(triggerArr[3]) + " " + ConvertSpaceStr(triggerArr[2]) + " " + ConvertSpaceStr(triggerArr[1]) + " ? " + ConvertSpaceStr(triggerArr[0]) + "";
  658. }
  659. /// <summary>
  660. /// 空字符串转换
  661. /// </summary>
  662. /// <param name="triggerStr"></param>
  663. /// <returns></returns>
  664. private string ConvertSpaceStr(string triggerStr)
  665. {
  666. return string.IsNullOrEmpty(triggerStr) ? "0" : triggerStr;
  667. }
  668. /// <summary>
  669. /// 获取下次运行时间。
  670. /// </summary>
  671. /// <param name="trigger"></param>
  672. /// <returns></returns>
  673. public string GetNextDate(ITrigger trigger)
  674. {
  675. var nextFireTime = trigger.GetNextFireTimeUtc();
  676. DateTime nextTime;
  677. string nextTimeStr = "";
  678. if (DateTime.TryParse(nextFireTime.ToString(), out nextTime))
  679. nextTimeStr = nextTime.ToString("yyyy-MM-dd HH:mm:ss");
  680. return nextTimeStr;
  681. }
  682. #endregion
  683. #region Pasued / Resume
  684. /// <summary>
  685. /// 暂停 Job
  686. /// </summary>
  687. /// <param name="key"></param>
  688. /// <returns></returns>
  689. public bool PausedJob(JobKey key)
  690. {
  691. if (!CheckJobIsExist(key))
  692. {
  693. ErrorMsg = key + " is not find!";
  694. return false;
  695. }
  696. Sched.PauseJob(key);
  697. return true;
  698. }
  699. /// <summary>
  700. /// 恢复 Job
  701. /// </summary>
  702. /// <param name="key"></param>
  703. /// <returns></returns>
  704. public bool ResumeJob(JobKey key)
  705. {
  706. if (!CheckJobIsExist(key))
  707. {
  708. ErrorMsg = key + " is not find!";
  709. return false;
  710. }
  711. Sched.PauseJob(key);
  712. return true;
  713. }
  714. /// <summary>
  715. /// 暂停 Job
  716. /// </summary>
  717. /// <param name="jobDetail"></param>
  718. /// <returns></returns>
  719. public bool PausedJob(IJobDetail jobDetail)
  720. {
  721. return PausedJob(jobDetail.Key);
  722. }
  723. /// <summary>
  724. /// 恢复 Job
  725. /// </summary>
  726. /// <param name="jobDetail"></param>
  727. /// <returns></returns>
  728. public bool ResumeJob(IJobDetail jobDetail)
  729. {
  730. return ResumeJob(jobDetail.Key);
  731. }
  732. /// <summary>
  733. /// 暂停 Job组
  734. /// </summary>
  735. /// <param name="jobGroupName"></param>
  736. public void PausedJobs(string jobGroupName)
  737. {
  738. Sched.PauseJobs(GroupMatcher<JobKey>.GroupEquals(jobGroupName));
  739. }
  740. /// <summary>
  741. /// 恢复 Job组
  742. /// </summary>
  743. /// <param name="jobGroupName"></param>
  744. public void ResumeJobs(string jobGroupName)
  745. {
  746. Sched.PauseJobs(GroupMatcher<JobKey>.GroupEquals(jobGroupName));
  747. }
  748. /// <summary>
  749. /// 暂停 Trigger
  750. /// </summary>
  751. /// <param name="key"></param>
  752. /// <returns></returns>
  753. public bool PausedTrigger(TriggerKey key)
  754. {
  755. if (!CheckTriggerIsExist(key))
  756. {
  757. ErrorMsg = key + " is not find!";
  758. return false;
  759. }
  760. Sched.PauseTrigger(key);
  761. return true;
  762. }
  763. /// <summary>
  764. /// 恢复 Trigger
  765. /// </summary>
  766. /// <param name="key"></param>
  767. /// <returns></returns>
  768. public bool ResumeTrigger(TriggerKey key)
  769. {
  770. if (!CheckTriggerIsExist(key))
  771. {
  772. ErrorMsg = key + " is not find!";
  773. return false;
  774. }
  775. Sched.PauseTrigger(key);
  776. return true;
  777. }
  778. /// <summary>
  779. /// 暂停 Trigger
  780. /// </summary>
  781. /// <param name="trigger"></param>
  782. /// <returns></returns>
  783. public bool PausedTrigger(ITrigger trigger)
  784. {
  785. return PausedTrigger(trigger.Key);
  786. }
  787. /// <summary>
  788. /// 恢复 Trigger
  789. /// </summary>
  790. /// <param name="trigger"></param>
  791. /// <returns></returns>
  792. public bool ResumeTrigger(ITrigger trigger)
  793. {
  794. return ResumeTrigger(trigger.Key);
  795. }
  796. /// <summary>
  797. /// 暂停 Trigger组
  798. /// </summary>
  799. /// <param name="triggerGroupName"></param>
  800. public void PausedTriggers(string triggerGroupName)
  801. {
  802. Sched.PauseTriggers(GroupMatcher<TriggerKey>.GroupEquals(triggerGroupName));
  803. }
  804. /// <summary>
  805. /// 恢复 Trigger组
  806. /// </summary>
  807. /// <param name="triggerGroupName"></param>
  808. public void ResumeTriggers(string triggerGroupName)
  809. {
  810. Sched.PauseTriggers(GroupMatcher<TriggerKey>.GroupEquals(triggerGroupName));
  811. }
  812. /// <summary>
  813. /// 暂停调度中所有的job任务
  814. /// </summary>
  815. public void PausedAll()
  816. {
  817. Sched.PauseAll();
  818. }
  819. /// <summary>
  820. /// 恢复调度中所有的job任务
  821. /// </summary>
  822. public void ResumeAll()
  823. {
  824. Sched.PauseAll();
  825. }
  826. #endregion
  827. #region Get Key
  828. /// <summary>
  829. /// 获取 Jobkey
  830. /// </summary>
  831. /// <param name="jobName"></param>
  832. /// <param name="jobGroupName"></param>
  833. /// <returns></returns>
  834. public JobKey GetJobKey(string jobName, string jobGroupName)
  835. {
  836. return JobKey.Create(jobName, jobGroupName);
  837. }
  838. /// <summary>
  839. /// 获取 JobKeys
  840. /// </summary>
  841. /// <param name="jobGroupName"></param>
  842. /// <returns></returns>
  843. public IReadOnlyCollection<JobKey> GetJobKeys(string jobGroupName)
  844. {
  845. return Sched.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(jobGroupName)).Result;
  846. }
  847. /// <summary>
  848. /// 获取 TriggerKey
  849. /// </summary>
  850. /// <param name="triggerName"></param>
  851. /// <param name="triggerGroupName"></param>
  852. /// <returns></returns>
  853. public TriggerKey GetTriggerKey(string triggerName, string triggerGroupName)
  854. {
  855. return new TriggerKey(triggerName, triggerGroupName);
  856. }
  857. /// <summary>
  858. /// 获取 TriggerKeys
  859. /// </summary>
  860. /// <param name="triggerGroupName"></param>
  861. /// <returns></returns>
  862. public IReadOnlyCollection<TriggerKey> GetTriggerKeys(string triggerGroupName)
  863. {
  864. return Sched.GetTriggerKeys(GroupMatcher<TriggerKey>.GroupEquals(triggerGroupName)).Result;
  865. }
  866. #endregion
  867. #region Check IsExist
  868. /// <summary>
  869. /// 检查调度是否启动
  870. /// </summary>
  871. /// <returns></returns>
  872. public bool CheckIsStarted()
  873. {
  874. return Sched.IsStarted;
  875. }
  876. /// <summary>
  877. /// 检查Job是否已存在
  878. /// </summary>
  879. /// <param name="jobName"></param>
  880. /// <param name="jobGroupName"></param>
  881. /// <returns></returns>
  882. public bool CheckJobIsExist(string jobName, string jobGroupName)
  883. {
  884. JobKey key = new JobKey(jobName, jobGroupName);
  885. return CheckJobIsExist(key);
  886. }
  887. /// <summary>
  888. /// 检查Job是否已存在;
  889. /// </summary>
  890. /// <param name="jobDetail"></param>
  891. /// <returns></returns>
  892. public bool CheckJobIsExist(IJobDetail jobDetail)
  893. {
  894. return CheckJobIsExist(jobDetail.Key);
  895. }
  896. /// <summary>
  897. /// 检查Job是否已存在;
  898. /// </summary>
  899. /// <param name="key"></param>
  900. /// <returns></returns>
  901. public bool CheckJobIsExist(JobKey key)
  902. {
  903. return Sched.CheckExists(key).Result;
  904. }
  905. /// <summary>
  906. /// 检查Trigger是否已存在;
  907. /// </summary>
  908. /// <param name="triggerName"></param>
  909. /// <param name="triggerGroupName"></param>
  910. /// <returns></returns>
  911. public bool CheckTriggerIsExist(string triggerName, string triggerGroupName)
  912. {
  913. TriggerKey key = new TriggerKey(triggerName, triggerGroupName);
  914. return CheckTriggerIsExist(key);
  915. }
  916. /// <summary>
  917. /// 检查Trigger是否已存在;
  918. /// </summary>
  919. /// <param name="trigger"></param>
  920. /// <returns></returns>
  921. public bool CheckTriggerIsExist(ITrigger trigger)
  922. {
  923. return CheckJobIsExist(trigger.JobKey);
  924. }
  925. /// <summary>
  926. /// 检查Trigger是否已存在;
  927. /// </summary>
  928. /// <param name="key"></param>
  929. /// <returns></returns>
  930. public bool CheckTriggerIsExist(TriggerKey key)
  931. {
  932. return Sched.CheckExists(key).Result;
  933. }
  934. #endregion
  935. #region Start / Stop
  936. /// <summary>
  937. /// 启动调度信息
  938. /// </summary>
  939. public void Start()
  940. {
  941. _log.Info("------- Starting ---------------------]");
  942. Sched.Start();
  943. _log.Info("------- Started ---------------------]");
  944. }
  945. /// <summary>
  946. /// 关闭调度信息
  947. /// </summary>
  948. public void Shutdown()
  949. {
  950. _log.Info("------- Shutting Down ---------------------");
  951. Sched.Shutdown(true);
  952. _log.Info("------- Shutdown Complete -----------------");
  953. }
  954. /// <summary>
  955. /// 启动 任务
  956. /// </summary>
  957. /// <param name="jobkey"></param>
  958. public void TriggerJob(JobKey jobkey)
  959. {
  960. Sched.TriggerJob(jobkey);
  961. }
  962. /// <summary>
  963. /// 启动 任务
  964. /// </summary>
  965. /// <param name="jobkey"></param>
  966. /// <param name="jobdatamap"></param>
  967. public void TriggerJob(JobKey jobkey, JobDataMap jobdatamap)
  968. {
  969. Sched.TriggerJob(jobkey, jobdatamap);
  970. }
  971. #endregion
  972. #region Reset Name
  973. /// <summary>
  974. /// 重置 jobName
  975. /// </summary>
  976. /// <param name="jobName"></param>
  977. /// <param name="jobGroupName"></param>
  978. public void ResetJobName(string jobName = null, string jobGroupName = null)
  979. {
  980. if (!string.IsNullOrEmpty(jobName))
  981. JobName = jobName;
  982. if (!string.IsNullOrEmpty(jobGroupName))
  983. JobGroupName = jobGroupName;
  984. }
  985. /// <summary>
  986. /// 重置 TriggerName
  987. /// </summary>
  988. /// <param name="triggerName"></param>
  989. /// <param name="triggerGroupName"></param>
  990. public void ResetTriggerName(string triggerName = null, string triggerGroupName = null)
  991. {
  992. if (!string.IsNullOrEmpty(triggerName))
  993. TriggerName = triggerName;
  994. if (!string.IsNullOrEmpty(triggerGroupName))
  995. TriggerGroupName = triggerGroupName;
  996. }
  997. #endregion
  998. }
  999. }