QuartzAsyncHelper.cs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using log4net;
  5. using Quartz;
  6. using Quartz.Impl;
  7. using Quartz.Impl.Matchers;
  8. namespace ShwasherSys.QuartzHelpers
  9. {
  10. public class QuartzAsyncHelper
  11. {
  12. public static QuartzAsyncHelper Instance { get; set; } = new QuartzAsyncHelper();
  13. #region Field Properties
  14. private readonly ILog _log = LogManager.GetLogger(typeof(QuartzAsyncHelper));
  15. public ISchedulerFactory SchedulerFactory { get; set; }
  16. public IScheduler Sched { get; set; }
  17. public string JobName { get; set; }
  18. public string JobGroupName { get; set; }
  19. public string TriggerName { get; set; }
  20. public string TriggerGroupName { get; set; }
  21. public IJobDetail JobDetail { get; set; }
  22. public ITrigger Trigger { get; set; }
  23. DateTimeOffset? TimeOffset { get; set; }
  24. public string ErrorMsg { get; set; }
  25. //public ICronTrigger CronTrigger { get; set; }
  26. //public ISimpleTrigger SimpleTrigger { get; set; }
  27. #endregion
  28. #region Initialize
  29. private async Task<IScheduler> GetScheduler()
  30. {
  31. IScheduler scheduler = null;
  32. try
  33. {
  34. scheduler = await SchedulerFactory.GetScheduler();
  35. }
  36. catch (SchedulerException e)
  37. {
  38. LogManager.GetLogger(typeof(QuartzAsyncHelper)).Info(e.Message);
  39. }
  40. return scheduler;
  41. }
  42. public QuartzAsyncHelper()
  43. {
  44. SchedulerFactory = new StdSchedulerFactory();
  45. Sched = GetScheduler().Result;
  46. }
  47. public QuartzAsyncHelper(string jobName, string jobGroupName) : this()
  48. {
  49. TriggerName = JobName = jobName;
  50. JobGroupName = JobGroupName = jobGroupName;
  51. }
  52. public QuartzAsyncHelper(string jobName, string jobGroupName, string triggerName, string triggerGroupName) : this(jobName, jobGroupName)
  53. {
  54. TriggerName = triggerName;
  55. JobGroupName = triggerGroupName;
  56. }
  57. public QuartzAsyncHelper(string jobName, string jobGroupName, IJobDetail jobDetail, ITrigger trigger) : this(jobName, jobGroupName)
  58. {
  59. JobDetail = jobDetail;
  60. Trigger = trigger;
  61. }
  62. public QuartzAsyncHelper(IJobDetail jobDetail, ITrigger trigger)
  63. {
  64. SchedulerFactory = new StdSchedulerFactory();
  65. Sched = SchedulerFactory.GetScheduler().Result;
  66. JobDetail = jobDetail;
  67. Trigger = trigger;
  68. }
  69. #endregion
  70. #region Create JobDetail
  71. /// <summary>
  72. /// 向Scheduler(调度程序)中添加Job
  73. /// </summary>
  74. /// <returns></returns>
  75. public async Task<bool> CreateJob()
  76. {
  77. if (JobDetail != null && Trigger != null)
  78. {
  79. if (Sched.IsShutdown)
  80. {
  81. SchedulerFactory = new StdSchedulerFactory();
  82. Sched = await SchedulerFactory.GetScheduler();
  83. }
  84. if (await CheckJobIsExist(JobDetail))
  85. ErrorMsg = "JobtType:" + JobDetail.Key + " 已存在!";
  86. TimeOffset = await Sched.ScheduleJob(JobDetail, Trigger);
  87. _log.Info("[" + JobDetail.Key + "] will run at: " + TimeOffset + "---->");
  88. return true;
  89. }
  90. return false;
  91. }
  92. /// <summary>
  93. /// 向Scheduler(调度程序)中添加Job
  94. /// </summary>
  95. /// <param name="jobDetail"></param>
  96. /// <param name="trigger"></param>
  97. /// <returns></returns>
  98. public async Task<bool> CreateJob(IJobDetail jobDetail, ITrigger trigger)
  99. {
  100. ErrorMsg = "";
  101. if (jobDetail != null && trigger != null)
  102. {
  103. if (Sched.IsShutdown)
  104. {
  105. SchedulerFactory = new StdSchedulerFactory();
  106. Sched = await SchedulerFactory.GetScheduler();
  107. }
  108. if (await CheckJobIsExist(jobDetail))
  109. ErrorMsg = "JobtType:[" + jobDetail.Key + "] Is Exist!";
  110. else
  111. {
  112. try
  113. {
  114. TimeOffset = await Sched.ScheduleJob(jobDetail, trigger);
  115. _log.Info("JobtType:[" + jobDetail.Key + "] will run at: " + TimeOffset + "---->");
  116. return true;
  117. }
  118. catch (Exception e)
  119. {
  120. _log.Error(e.Message);
  121. ErrorMsg = "System Error!";
  122. }
  123. }
  124. }
  125. else
  126. {
  127. ErrorMsg = "JobDetail/Trigger is null";
  128. }
  129. return false;
  130. }
  131. /// <summary>
  132. /// 向Scheduler(调度程序)中添加Job
  133. /// </summary>
  134. /// <param name="jobType"></param>
  135. /// <param name="trigger"></param>
  136. /// <param name="jobName"></param>
  137. /// <param name="jobGroupName"></param>
  138. /// <returns></returns>
  139. public async Task<bool> CreateJob(Type jobType, ITrigger trigger, string jobName = null, string jobGroupName = null)
  140. {
  141. IJobDetail jobDetail = GetJobDetail(jobType, jobName, jobGroupName);
  142. if (jobDetail == null)
  143. return false;
  144. return await CreateJob(jobDetail, trigger);
  145. }
  146. /// <summary>
  147. /// 向Scheduler(调度程序)中添加Job
  148. /// </summary>
  149. /// <param name="jobType"></param>
  150. /// <param name="triggerStr">
  151. /// 触发器参数:【"开始时间"|"开始时间单位(参照IntervalUnit)"|"间隔时间"|"间隔时间单位(参照IntervalUnit)"|"重复次数(0代表无限循环)"】
  152. /// 【"cronExpStr"】(特定时间执行,填*代表每年每月...,填具体值代表特定值(多个值,间隔、范围值用-,a/b 指 从a开始,每隔b 触发一次))
  153. /// </param>
  154. /// <param name="triggerType">触发器类型</param>
  155. /// <param name="jobName"></param>
  156. /// <param name="jobGroupName"></param>
  157. /// <returns></returns>
  158. public async Task<bool> CreateJob(Type jobType, string triggerStr, TriggerType triggerType = TriggerType.SimpleTrigger, string jobName = null, string jobGroupName = null)
  159. {
  160. IJobDetail jobDetail = GetJobDetail(jobType, jobName, jobGroupName);
  161. if (jobDetail == null)
  162. return false;
  163. ITrigger trigger;
  164. switch (triggerType)
  165. {
  166. #region SimpleTrigger
  167. case TriggerType.SimpleTrigger:
  168. trigger = await GetSimpleTrigger(triggerStr);
  169. if (trigger != null)
  170. return await CreateJob(jobDetail, trigger);
  171. break;
  172. #endregion
  173. #region CronTrigger
  174. case TriggerType.CronTrigger:
  175. string cronExpStr = triggerStr;
  176. //if (!string.IsNullOrEmpty(triggerArr[0]))
  177. // cronExpStr = GetCronExpString(triggerArr[0]);
  178. //else if (triggerArr.Length == 2)
  179. // cronExpStr = triggerArr[1];
  180. trigger = await GetCronTrigger(cronExpStr);
  181. if (trigger != null)
  182. return await CreateJob(jobDetail, trigger);
  183. break;
  184. #endregion
  185. }
  186. return false;
  187. }
  188. /// <summary>
  189. /// 向Scheduler(调度程序)中添加Job
  190. /// </summary>
  191. /// <param name="jobType"></param>
  192. /// <param name="cronExpStr">CronSchedule 触发器表达式</param>
  193. /// <param name="jobName"></param>
  194. /// <param name="jobGroupName"></param>
  195. /// <returns></returns>
  196. public async Task<bool> CreateJob(Type jobType, string cronExpStr, string jobName = null, string jobGroupName = null)
  197. {
  198. IJobDetail jobDetail = GetJobDetail(jobType, jobName, jobGroupName);
  199. if (jobDetail == null)
  200. return false;
  201. ITrigger trigger = await GetCronTrigger(cronExpStr);
  202. if (trigger != null)
  203. return await CreateJob(jobDetail, trigger);
  204. return false;
  205. }
  206. /// <summary>
  207. /// 向Scheduler(调度程序)中添加多个job任务
  208. /// </summary>
  209. /// <param name="triggersAndJobs"></param>
  210. /// <param name="replace"></param>
  211. public async Task CreateJobs(IReadOnlyDictionary<IJobDetail, IReadOnlyCollection<ITrigger>> triggersAndJobs, bool replace)
  212. {
  213. await Sched.ScheduleJobs(triggersAndJobs, replace);
  214. }
  215. /// <summary>
  216. /// 添加 JobDetail
  217. /// </summary>
  218. /// <param name="jobdetail"></param>
  219. /// <param name="replace">是否覆盖</param>
  220. public async Task AddJob(IJobDetail jobdetail, bool replace)
  221. {
  222. await Sched.AddJob(jobdetail, replace);
  223. }
  224. #endregion
  225. #region Get JobDetail
  226. /// <summary>
  227. /// 获取 JobDetail
  228. /// </summary>
  229. /// <param name="key"></param>
  230. /// <returns></returns>
  231. public async Task<IJobDetail> GetJobDetail(JobKey key)
  232. {
  233. return await CheckJobIsExist(key) ? await Sched.GetJobDetail(key) : null;
  234. }
  235. /// <summary>
  236. /// 获取 JobDetail
  237. /// </summary>
  238. /// <param name="jobName"></param>
  239. /// <param name="jobGroupName"></param>
  240. /// <returns></returns>
  241. public async Task<IJobDetail> GetJobDetail(string jobName, string jobGroupName)
  242. {
  243. JobKey key = GetJobKey(jobName, jobGroupName);
  244. return await GetJobDetail(key);
  245. }
  246. /// <summary>
  247. /// 构造 JobDetail
  248. /// </summary>
  249. /// <param name="jobType"></param>
  250. /// <param name="jobName"></param>
  251. /// <param name="jobGroupName"></param>
  252. /// <returns></returns>
  253. public IJobDetail GetJobDetail(Type jobType, string jobName = null, string jobGroupName = null)
  254. {
  255. jobName = jobName ?? JobName;
  256. jobGroupName = jobGroupName ?? JobGroupName;
  257. if (string.IsNullOrEmpty(jobName) || string.IsNullOrEmpty(jobGroupName))
  258. {
  259. ErrorMsg = "jobName/jobGroupName is empty!";
  260. return null;
  261. }
  262. IJobDetail jobDetail = null;
  263. try
  264. {
  265. jobDetail = new JobDetailImpl(jobName, jobGroupName, jobType);
  266. }
  267. catch (Exception e)
  268. {
  269. _log.Error(e.Message);
  270. ErrorMsg = e.Message;
  271. }
  272. return jobDetail;
  273. }
  274. /// <summary>
  275. /// 获取job 组名
  276. /// </summary>
  277. /// <returns></returns>
  278. public async Task<IReadOnlyCollection<string>> GetJobGroupNames()
  279. {
  280. return await Sched.GetJobGroupNames();
  281. }
  282. /// <summary>
  283. /// 给JobDetail设置参数
  284. /// </summary>
  285. /// <param name="jobDetail"></param>
  286. /// <param name="parmDic">参数的值</param>
  287. /// <param name="parmKey">参数的键</param>
  288. public void SetJobDetailParm(IJobDetail jobDetail, Dictionary<string, object> parmDic, string parmKey = "jobParm")
  289. {
  290. var map = jobDetail.JobDataMap.Get(parmKey);
  291. if (map != null)
  292. {
  293. jobDetail.JobDataMap[parmKey] = parmDic;
  294. }
  295. else
  296. {
  297. jobDetail.JobDataMap.Put(parmKey, parmDic);
  298. }
  299. }
  300. #endregion
  301. #region Delete JobDetail
  302. public async Task<bool> DeleteJob(string jobName = null, string jobGroupName = null)
  303. {
  304. jobName = jobName ?? JobName;
  305. jobGroupName = jobGroupName ?? JobGroupName;
  306. return await DeleteJob(GetJobKey(jobName, jobGroupName));
  307. }
  308. public async Task<bool> DeleteJob(IJobDetail jobDetail)
  309. {
  310. return jobDetail != null && await Sched.DeleteJob(jobDetail.Key);
  311. }
  312. public async Task<bool> DeleteJob(JobKey key)
  313. {
  314. return await Sched.DeleteJob(key);
  315. }
  316. public async Task<bool> DeleteJobs(string jobGroupName = null)
  317. {
  318. jobGroupName = jobGroupName ?? JobGroupName;
  319. var keys = await GetJobKeys(jobGroupName);
  320. return await Sched.DeleteJobs(keys);
  321. }
  322. public async Task<bool> DeleteJobs(List<JobKey> keys)
  323. {
  324. return await Sched.DeleteJobs(keys);
  325. }
  326. /*
  327. * 首先从Scheduler.scheduleJob(JobDetail jobDetail, Trigger trigger) 调度job,实际上就是将job存储到RAM中的jobsByGroup,jobsByKey对应的Map中, 将trigger存储到triggers(List),triggersByKey,triggersByGroup对应的Map中,及timeTriggers的Treeset中。
  328. * Scheduler.unscheduleJob(TriggerKey triggerKey) 就是将triggerKey从triggersByKey,triggersByGroup,triggers,timeTriggers中移除;
  329. * Scheduler.deleteJob(JobKey jobKey)除了从容器triggers中的TriggerWrapper的JobKey为jobKey的List<TriggerWrapper>,并unscheduleJob(TriggerKey triggerKey)列表 List<TriggerWrapper>中的所有TriggerWrapper,同时从jobsByKey,jobsByGroup的移除对应jobKey的相关信息
  330. */
  331. /// <summary>
  332. /// 停止调度Job任务
  333. /// </summary>
  334. /// <param name="triggerkey"></param>
  335. /// <returns></returns>
  336. /// <para>If the related job does not have any other triggers, and the job is
  337. /// not durable, then the job will also be deleted.</para>
  338. public async Task<bool> UnscheduleJob(TriggerKey triggerkey)
  339. {
  340. return await Sched.UnscheduleJob(triggerkey);
  341. }
  342. /// <summary>
  343. /// 停止多个调度Job任务
  344. /// </summary>
  345. /// <param name="triggerkeys"></param>
  346. /// <returns></returns>
  347. public async Task<bool> UnscheduleJobs(List<TriggerKey> triggerkeys)
  348. {
  349. return await Sched.UnscheduleJobs(triggerkeys);
  350. }
  351. /// <summary>
  352. /// 重新恢复触发器相关的job任务
  353. /// </summary>
  354. /// <param name="triggerkey"></param>
  355. /// <param name="trigger"></param>
  356. /// <returns></returns>
  357. public async Task<DateTimeOffset?> RescheduleJob(TriggerKey triggerkey, ITrigger trigger)
  358. {
  359. return await Sched.RescheduleJob(triggerkey, trigger);
  360. }
  361. #endregion
  362. #region Get Trigger
  363. public async Task<ITrigger> GetTrigger(TriggerKey key)
  364. {
  365. return await CheckTriggerIsExist(key) ? await Sched.GetTrigger(key) : null;
  366. }
  367. public async Task<ITrigger> GetTrigger(string triggerName, string triggerGroupName)
  368. {
  369. var key = GetTriggerKey(triggerName, triggerGroupName);
  370. return await GetTrigger(key);
  371. }
  372. /// <summary>
  373. /// 获取 指定 Job 里的所有 Trigger
  374. /// </summary>
  375. /// <param name="key"></param>
  376. /// <returns></returns>
  377. public async Task<IReadOnlyCollection<ITrigger>> GetTriggersByJob(JobKey key)
  378. {
  379. return await CheckJobIsExist(key) ? await Sched.GetTriggersOfJob(key) : null;
  380. }
  381. /// <summary>
  382. /// 获取 指定 TriggerGroup 里的所有 Trigger
  383. /// </summary>
  384. /// <param name="triggerGroupName"></param>
  385. /// <returns></returns>
  386. public async Task<IReadOnlyCollection<ITrigger>> GetTriggersByGroup(string triggerGroupName)
  387. {
  388. var triggerList = new List<ITrigger>();
  389. var keys = await GetTriggerKeys(triggerGroupName);
  390. foreach (var triggerKey in keys)
  391. {
  392. triggerList.Add(await GetTrigger(triggerKey));
  393. }
  394. return triggerList;
  395. }
  396. /// <summary>
  397. /// 获取所有的 Trigger
  398. /// </summary>
  399. /// <returns></returns>
  400. public async Task<IReadOnlyCollection<ITrigger>> GetTriggers()
  401. {
  402. var triggerList = new List<ITrigger>();
  403. var triggerGroupNames = await GetTriggerGroupNames();
  404. foreach (var name in triggerGroupNames)
  405. {
  406. triggerList.AddRange(await GetTriggersByGroup(name));
  407. }
  408. return triggerList;
  409. }
  410. /// <summary>
  411. /// 获取暂停的 Trigger
  412. /// </summary>
  413. /// <returns></returns>
  414. public async Task<IReadOnlyCollection<ITrigger>> GetPausedTriggers()
  415. {
  416. var triggerList = new List<ITrigger>();
  417. var triggerGroupNames = await GetPausedTriggerGroupNames();
  418. foreach (var name in triggerGroupNames)
  419. {
  420. triggerList.AddRange(await GetTriggersByGroup(name));
  421. }
  422. return triggerList;
  423. }
  424. /// <summary>
  425. /// 获取 所有的 TriggerGroupName
  426. /// </summary>
  427. /// <returns></returns>
  428. public async Task<IReadOnlyCollection<string>> GetTriggerGroupNames()
  429. {
  430. return await Sched.GetTriggerGroupNames();
  431. }
  432. /// <summary>
  433. /// 获取 暂停的 TriggerGroupName
  434. /// </summary>
  435. /// <returns></returns>
  436. public async Task<IReadOnlyCollection<string>> GetPausedTriggerGroupNames()
  437. {
  438. return await Sched.GetPausedTriggerGroups();
  439. }
  440. /// <summary>
  441. /// 获取 指定 Trigger 的 TriggerState
  442. /// </summary>
  443. /// <param name="key"></param>
  444. /// <returns></returns>
  445. public async Task<TriggerState> GetTriggerState(TriggerKey key)
  446. {
  447. return await CheckTriggerIsExist(key) ? await Sched.GetTriggerState(key) : TriggerState.None;
  448. }
  449. /// <summary>
  450. /// 根据参数数组(1个|4个)创建SimpleTrigger
  451. /// </summary>
  452. /// <param name="triggerStr"></param>
  453. /// <param name="triggerName"></param>
  454. /// <param name="triggerGroupName"></param>
  455. /// <returns></returns>
  456. public async Task<ITrigger> GetSimpleTrigger(string triggerStr, string triggerName = null, string triggerGroupName = null)
  457. {
  458. ITrigger trigger;
  459. if (string.IsNullOrEmpty(triggerName)) triggerName = TriggerName;
  460. if (string.IsNullOrEmpty(triggerGroupName)) triggerGroupName = TriggerName;
  461. if (await CheckTriggerIsExist(triggerName, triggerGroupName))
  462. {
  463. ErrorMsg = "Trigger[" + triggerGroupName + "." + triggerName + "] Is Exist";
  464. return null;
  465. }
  466. string[] triggerArr = triggerStr.Split('|');
  467. #region Length = 1
  468. if (triggerArr.Length == 1)
  469. {
  470. ErrorMsg = "参数 [1]TriggerArray 有误,不能解析。";
  471. if (!DateTimeOffset.TryParse(triggerArr[0], out var startTime)) return null;
  472. //int start, startUnit;
  473. //if (!int.TryParse(triggerArr[0], out start)) return false;
  474. //if (!int.TryParse(triggerArr[1], out startUnit)) return false;
  475. //DateTimeOffset startTime = DateBuilder.FutureDate(start, (IntervalUnit)startUnit);
  476. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  477. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime).Build();
  478. _log.InfoFormat("Trigger----{0}----{1}----", triggerArr[0], triggerArr[1]);
  479. ErrorMsg = "";
  480. return trigger;
  481. }
  482. #endregion
  483. #region Length = 4
  484. if (triggerArr.Length == 4)
  485. {
  486. ErrorMsg = "参数 [4]TriggerArray 有误,不能解析。";
  487. DateTimeOffset startTime;
  488. int interval, intervalUnit, repeatCount;
  489. if (!DateTimeOffset.TryParse(triggerArr[0], out startTime)) return null;
  490. if (!int.TryParse(triggerArr[1], out interval)) return null;
  491. if (!int.TryParse(triggerArr[2], out intervalUnit)) return null;
  492. // = DateBuilder.FutureDate(future, (IntervalUnit)futureUnit);
  493. if (string.IsNullOrEmpty(triggerArr[3]))
  494. repeatCount = 0;
  495. else if (!int.TryParse(triggerArr[3], out repeatCount)) return null;
  496. switch (repeatCount)
  497. {
  498. case 0:
  499. switch (intervalUnit)
  500. {
  501. default:
  502. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  503. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  504. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).RepeatForever()).Build();
  505. break;
  506. case 1:
  507. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  508. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  509. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).RepeatForever()).Build();
  510. break;
  511. case 2:
  512. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  513. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  514. .WithSimpleSchedule(x => x.WithIntervalInMinutes(interval).RepeatForever()).Build();
  515. break;
  516. case 3:
  517. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  518. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  519. .WithSimpleSchedule(x => x.WithIntervalInHours(interval).RepeatForever()).Build();
  520. break;
  521. }
  522. break;
  523. default:
  524. repeatCount = repeatCount - 1;
  525. switch (intervalUnit)
  526. {
  527. default:
  528. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  529. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  530. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).WithRepeatCount(repeatCount)).Build();
  531. break;
  532. case 1:
  533. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  534. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  535. .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).WithRepeatCount(repeatCount)).Build();
  536. break;
  537. case 2:
  538. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  539. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  540. .WithSimpleSchedule(x => x.WithIntervalInMinutes(interval).WithRepeatCount(repeatCount)).Build();
  541. break;
  542. case 3:
  543. trigger = (ISimpleTrigger)TriggerBuilder.Create()
  544. .WithIdentity(triggerName, triggerGroupName).StartAt(startTime)
  545. .WithSimpleSchedule(x => x.WithIntervalInHours(interval).WithRepeatCount(repeatCount)).Build();
  546. break;
  547. }
  548. break;
  549. }
  550. _log.InfoFormat("Trigger----{0}----{1}----{2}----{3}----", triggerArr[0], triggerArr[1], triggerArr[2],
  551. triggerArr[3]);
  552. ErrorMsg = "";
  553. return trigger;
  554. }
  555. #endregion
  556. ErrorMsg = "参数 TriggerArray 有误,不能解析。";
  557. return null;
  558. }
  559. /// <summary>
  560. /// 根据表达式创建CronTrigger
  561. /// </summary>
  562. /// <param name="cronExpStr"></param>
  563. /// <param name="triggerName"></param>
  564. /// <param name="triggerGroupName"></param>
  565. /// <returns></returns>
  566. public async Task<ITrigger> GetCronTrigger(string cronExpStr, string triggerName = null, string triggerGroupName = null)
  567. {
  568. ITrigger trigger = null;
  569. if (string.IsNullOrEmpty(triggerName)) triggerName = TriggerName;
  570. if (string.IsNullOrEmpty(triggerGroupName)) triggerGroupName = TriggerName;
  571. if (await CheckTriggerIsExist(triggerName, triggerGroupName))
  572. {
  573. ErrorMsg = "Trigger[" + triggerGroupName + "." + triggerName + "] Is Exist";
  574. return null;
  575. }
  576. try
  577. {
  578. trigger = (ICronTrigger)TriggerBuilder.Create()
  579. .WithIdentity(triggerName, triggerGroupName).WithCronSchedule(cronExpStr).Build();
  580. return trigger;
  581. }
  582. catch (Exception e)
  583. {
  584. _log.Error(e.Message);
  585. ErrorMsg = e.Message;
  586. }
  587. return trigger;
  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 async Task<bool> PausedJob(JobKey key)
  690. {
  691. if (!await CheckJobIsExist(key))
  692. {
  693. ErrorMsg = key + " is not find!";
  694. return false;
  695. }
  696. await Sched.PauseJob(key);
  697. return true;
  698. }
  699. /// <summary>
  700. /// 恢复 Job
  701. /// </summary>
  702. /// <param name="key"></param>
  703. /// <returns></returns>
  704. public async Task<bool> ResumeJob(JobKey key)
  705. {
  706. if (!await CheckJobIsExist(key))
  707. {
  708. ErrorMsg = key + " is not find!";
  709. return false;
  710. }
  711. await Sched.PauseJob(key);
  712. return true;
  713. }
  714. /// <summary>
  715. /// 暂停 Job
  716. /// </summary>
  717. /// <param name="jobDetail"></param>
  718. /// <returns></returns>
  719. public async Task<bool> PausedJob(IJobDetail jobDetail)
  720. {
  721. return await PausedJob(jobDetail.Key);
  722. }
  723. /// <summary>
  724. /// 恢复 Job
  725. /// </summary>
  726. /// <param name="jobDetail"></param>
  727. /// <returns></returns>
  728. public async Task<bool> ResumeJob(IJobDetail jobDetail)
  729. {
  730. return await ResumeJob(jobDetail.Key);
  731. }
  732. /// <summary>
  733. /// 暂停 Job组
  734. /// </summary>
  735. /// <param name="jobGroupName"></param>
  736. public async Task PausedJobs(string jobGroupName)
  737. {
  738. await Sched.PauseJobs(GroupMatcher<JobKey>.GroupEquals(jobGroupName));
  739. }
  740. /// <summary>
  741. /// 恢复 Job组
  742. /// </summary>
  743. /// <param name="jobGroupName"></param>
  744. public async Task ResumeJobs(string jobGroupName)
  745. {
  746. await Sched.PauseJobs(GroupMatcher<JobKey>.GroupEquals(jobGroupName));
  747. }
  748. /// <summary>
  749. /// 暂停 Trigger
  750. /// </summary>
  751. /// <param name="key"></param>
  752. /// <returns></returns>
  753. public async Task<bool> PausedTrigger(TriggerKey key)
  754. {
  755. if (!await CheckTriggerIsExist(key))
  756. {
  757. ErrorMsg = key + " is not find!";
  758. return false;
  759. }
  760. await Sched.PauseTrigger(key);
  761. return true;
  762. }
  763. /// <summary>
  764. /// 恢复 Trigger
  765. /// </summary>
  766. /// <param name="key"></param>
  767. /// <returns></returns>
  768. public async Task<bool> ResumeTrigger(TriggerKey key)
  769. {
  770. if (!await CheckTriggerIsExist(key))
  771. {
  772. ErrorMsg = key + " is not find!";
  773. return false;
  774. }
  775. await Sched.PauseTrigger(key);
  776. return true;
  777. }
  778. /// <summary>
  779. /// 暂停 Trigger
  780. /// </summary>
  781. /// <param name="trigger"></param>
  782. /// <returns></returns>
  783. public async Task<bool> PausedTrigger(ITrigger trigger)
  784. {
  785. return await PausedTrigger(trigger.Key);
  786. }
  787. /// <summary>
  788. /// 恢复 Trigger
  789. /// </summary>
  790. /// <param name="trigger"></param>
  791. /// <returns></returns>
  792. public async Task<bool> ResumeTrigger(ITrigger trigger)
  793. {
  794. return await ResumeTrigger(trigger.Key);
  795. }
  796. /// <summary>
  797. /// 暂停 Trigger组
  798. /// </summary>
  799. /// <param name="triggerGroupName"></param>
  800. public async Task PausedTriggers(string triggerGroupName)
  801. {
  802. await Sched.PauseTriggers(GroupMatcher<TriggerKey>.GroupEquals(triggerGroupName));
  803. }
  804. /// <summary>
  805. /// 恢复 Trigger组
  806. /// </summary>
  807. /// <param name="triggerGroupName"></param>
  808. public async Task ResumeTriggers(string triggerGroupName)
  809. {
  810. await 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 async Task<IReadOnlyCollection<JobKey>> GetJobKeys(string jobGroupName)
  844. {
  845. return await Sched.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(jobGroupName));
  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 async Task<IReadOnlyCollection<TriggerKey>> GetTriggerKeys(string triggerGroupName)
  863. {
  864. return await Sched.GetTriggerKeys(GroupMatcher<TriggerKey>.GroupEquals(triggerGroupName));
  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 async Task<bool> CheckJobIsExist(string jobName, string jobGroupName)
  883. {
  884. JobKey key = new JobKey(jobName, jobGroupName);
  885. return await CheckJobIsExist(key);
  886. }
  887. /// <summary>
  888. /// 检查Job是否已存在;
  889. /// </summary>
  890. /// <param name="jobDetail"></param>
  891. /// <returns></returns>
  892. public async Task<bool> CheckJobIsExist(IJobDetail jobDetail)
  893. {
  894. return await CheckJobIsExist(jobDetail.Key);
  895. }
  896. /// <summary>
  897. /// 检查Job是否已存在;
  898. /// </summary>
  899. /// <param name="key"></param>
  900. /// <returns></returns>
  901. public async Task<bool> CheckJobIsExist(JobKey key)
  902. {
  903. return await Sched.CheckExists(key);
  904. }
  905. /// <summary>
  906. /// 检查Trigger是否已存在;
  907. /// </summary>
  908. /// <param name="triggerName"></param>
  909. /// <param name="triggerGroupName"></param>
  910. /// <returns></returns>
  911. public async Task<bool> CheckTriggerIsExist(string triggerName, string triggerGroupName)
  912. {
  913. TriggerKey key = new TriggerKey(triggerName, triggerGroupName);
  914. return await CheckTriggerIsExist(key);
  915. }
  916. /// <summary>
  917. /// 检查Trigger是否已存在;
  918. /// </summary>
  919. /// <param name="trigger"></param>
  920. /// <returns></returns>
  921. public async Task<bool> CheckTriggerIsExist(ITrigger trigger)
  922. {
  923. return await CheckJobIsExist(trigger.JobKey);
  924. }
  925. /// <summary>
  926. /// 检查Trigger是否已存在;
  927. /// </summary>
  928. /// <param name="key"></param>
  929. /// <returns></returns>
  930. public async Task<bool> CheckTriggerIsExist(TriggerKey key)
  931. {
  932. return await Sched.CheckExists(key);
  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. public enum TriggerType
  1000. {
  1001. SimpleTrigger = 1,
  1002. CronTrigger = 2
  1003. }
  1004. }