SeqenecRoutine.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Specialized;
  4. using System.Linq;
  5. using System.Text;
  6. using Aitex.Core.RT.Event;
  7. using Aitex.Core.RT.Log;
  8. using Aitex.Core.Util;
  9. namespace Aitex.Core.RT.Routine
  10. {
  11. public class RoutineFaildException : ApplicationException
  12. {
  13. public RoutineFaildException() { }
  14. public RoutineFaildException(string message)
  15. : base(message) { }
  16. }
  17. public class RoutineBreakException : ApplicationException
  18. {
  19. public RoutineBreakException() { }
  20. public RoutineBreakException(string message)
  21. : base(message) { }
  22. }
  23. public enum RoutineState
  24. {
  25. Running,
  26. Failed,
  27. Timeout,
  28. Finished,
  29. }
  30. public class RoutineResult
  31. {
  32. public RoutineState Result;
  33. public string ErrorMessage;
  34. }
  35. public class SeqenecRoutine
  36. {
  37. //timer, 计算routine时间
  38. protected DeviceTimer counter = new DeviceTimer();
  39. protected DeviceTimer delayTimer = new DeviceTimer();
  40. private enum STATE
  41. {
  42. IDLE,
  43. WAIT,
  44. }
  45. public int TokenId
  46. {
  47. get { return _id; }
  48. }
  49. private int _id; //step index
  50. protected List<int> _historySteps = new List<int>();
  51. protected List<int> _waitSteps = new List<int>();
  52. /// <summary>
  53. /// already done steps
  54. /// </summary>
  55. private Stack<int> _steps = new Stack<int>();
  56. public Stack<int> Steps
  57. {
  58. get
  59. {
  60. return _steps;
  61. }
  62. set
  63. {
  64. _steps = value;
  65. }
  66. }
  67. private STATE state; //step state //idel,wait,
  68. //loop control
  69. private int loop = 0;
  70. private int loopCount = 0;
  71. private int loopID = 0;
  72. protected DeviceTimer timer = new DeviceTimer();
  73. public DeviceTimer Timer => timer;
  74. public int LoopCounter
  75. {
  76. get { return loop; }
  77. set { loop = value; }
  78. }
  79. public int LoopTotalTime { get { return loopCount; } }
  80. // public int Timeout { get { return (int)(timer.GetTotalTime() / 1000); } }
  81. //状态持续时间,单位为秒
  82. public int Elapsed { get { return (int)(timer.GetElapseTime() / 1000); } }
  83. protected RoutineResult RoutineToken = new RoutineResult() { Result = RoutineState.Running };
  84. protected bool IsCurrentStepExcuteFailed { get; private set; }
  85. //状态持续时间,单位为秒
  86. private double _pauseTime;
  87. public void Reset()
  88. {
  89. _id = 0;
  90. _steps.Clear();
  91. loop = 0;
  92. loopCount = 0;
  93. IsCurrentStepExcuteFailed = false;
  94. state = STATE.IDLE;
  95. counter.Start(60*60*100); //默认1小时
  96. RoutineToken.Result = RoutineState.Running;
  97. }
  98. public void ResetState()
  99. {
  100. state = STATE.IDLE;
  101. }
  102. protected void PerformRoutineStep(int id, Func<RoutineState> execution, RoutineResult result)
  103. {
  104. if (!Acitve(id))
  105. return;
  106. result.Result = execution();
  107. }
  108. #region interface
  109. public void StopLoop()
  110. {
  111. loop = loopCount;
  112. }
  113. public Tuple<bool, Result> Loop<T>(T id, Func<bool> func, int count)
  114. {
  115. int idx = Convert.ToInt32(id);
  116. bool bActive = Acitve(idx);
  117. if (bActive)
  118. {
  119. if (!func())
  120. {
  121. return Tuple.Create(bActive, Result.FAIL); //执行错误
  122. }
  123. loopID = idx;
  124. loopCount = count;
  125. next();
  126. return Tuple.Create(true, Result.RUN);
  127. }
  128. return Tuple.Create(false, Result.RUN);
  129. }
  130. public Tuple<bool, Result> EndLoop<T>(T id, Func<bool> func)
  131. {
  132. int idx = Convert.ToInt32(id);
  133. bool bActive = Acitve(idx);
  134. if (bActive)
  135. {
  136. if (++loop >= loopCount) //Loop 结束
  137. {
  138. if (!func())
  139. {
  140. return Tuple.Create(bActive, Result.FAIL); //执行错误
  141. }
  142. loop = 0;
  143. loopCount = 0; // Loop 结束时,当前loop和loop总数都清零
  144. next();
  145. return Tuple.Create(true, Result.RUN);
  146. }
  147. //继续下一LOOP
  148. next(loopID);
  149. return Tuple.Create(true, Result.RUN);
  150. }
  151. return Tuple.Create(false, Result.RUN);
  152. }
  153. public Tuple<bool, Result> ExecuteAndWait<T>(T id, IRoutine routine)
  154. {
  155. int idx = Convert.ToInt32(id);
  156. bool bActive = Acitve(idx);
  157. if (bActive)
  158. {
  159. if (state == STATE.IDLE)
  160. {
  161. Result startRet = routine.Start();
  162. if (startRet == Result.FAIL)
  163. {
  164. return Tuple.Create(true, Result.FAIL); //执行错误
  165. }else if (startRet == Result.DONE)
  166. {
  167. next();
  168. return Tuple.Create(true, Result.DONE);
  169. }
  170. state = STATE.WAIT;
  171. }
  172. Result ret = routine.Monitor();
  173. if (ret == Result.DONE)
  174. {
  175. next();
  176. return Tuple.Create(true, Result.DONE);
  177. }
  178. else if (ret == Result.FAIL || ret == Result.TIMEOUT)
  179. {
  180. return Tuple.Create(true, Result.FAIL);
  181. }
  182. else
  183. {
  184. return Tuple.Create(true, Result.RUN);
  185. }
  186. }
  187. return Tuple.Create(false, Result.RUN);
  188. }
  189. public Tuple<bool, Result> ExecuteAndWait<T>(T id, List<IRoutine> routines)
  190. {
  191. int idx = Convert.ToInt32(id);
  192. bool bActive = Acitve(idx);
  193. if (bActive)
  194. {
  195. if (state == STATE.IDLE)
  196. {
  197. foreach (var item in routines)
  198. {
  199. if (item.Start() == Result.FAIL)
  200. return Tuple.Create(true, Result.FAIL);
  201. }
  202. state = STATE.WAIT;
  203. }
  204. //wait all sub failed or completedboo
  205. bool bFail = false;
  206. bool bDone = true;
  207. foreach (var item in routines)
  208. {
  209. Result ret = item.Monitor();
  210. bDone &= (ret == Result.FAIL || ret == Result.DONE);
  211. bFail |= ret == Result.FAIL;
  212. }
  213. if (bDone)
  214. {
  215. next();
  216. if(bFail)
  217. return Tuple.Create(true, Result.FAIL);
  218. return Tuple.Create(true, Result.DONE);
  219. }
  220. return Tuple.Create(true, Result.RUN);
  221. }
  222. return Tuple.Create(false, Result.RUN);
  223. }
  224. public Tuple<bool, Result> Check<T>(T id, Func<bool> func) //顺序执行
  225. {
  226. return Check(Check(Convert.ToInt32(id), func));
  227. }
  228. public Tuple<bool, Result> Execute<T>(T id, Func<bool> func) //顺序执行
  229. {
  230. return Check(execute(Convert.ToInt32(id), func));
  231. }
  232. public Tuple<bool, Result> Wait<T>(T id, Func<bool> func, double timeout = int.MaxValue) //Wait condition
  233. {
  234. return Check(wait(Convert.ToInt32(id), func, timeout));
  235. }
  236. public Tuple<bool, Result> Wait<T>(T id, Func<bool?> func, double timeout = int.MaxValue) //Wait condition
  237. {
  238. return Check(wait(Convert.ToInt32(id), func, timeout));
  239. }
  240. public Tuple<bool, Result> ExecuteAndWait<T>(T id, Func<bool> execute, Func<bool?> check, double timeout = int.MaxValue)
  241. {
  242. int idx = Convert.ToInt32(id);
  243. bool bActive = Acitve(idx);
  244. bool? bExecute = false;
  245. if (bActive)
  246. {
  247. if (state == STATE.IDLE)
  248. {
  249. if (!execute())
  250. {
  251. return Tuple.Create(bActive, Result.FAIL); //执行错误
  252. }
  253. timer.Start(timeout);
  254. state = STATE.WAIT;
  255. }
  256. bExecute = check();
  257. if (bExecute == null)
  258. {
  259. return Tuple.Create(bActive, Result.FAIL); //Termianate
  260. }
  261. else
  262. {
  263. if (bExecute.Value) //检查Success, next
  264. {
  265. next();
  266. return Tuple.Create(true, Result.RUN);
  267. }
  268. }
  269. if(timer.IsTimeout())
  270. return Tuple.Create(true, Result.TIMEOUT);
  271. return Tuple.Create(true, Result.RUN);
  272. }
  273. return Tuple.Create(false, Result.RUN);
  274. }
  275. public Tuple<bool, Result> ExecuteAndWait<T>(T id, Func<bool> execute, Func<bool?> check, Func<double> time)
  276. {
  277. int idx = Convert.ToInt32(id);
  278. bool bActive = Acitve(idx);
  279. bool? bExecute = false;
  280. double timeout = 0;
  281. if (bActive)
  282. {
  283. if (state == STATE.IDLE)
  284. {
  285. timeout = time();
  286. if (!execute())
  287. {
  288. return Tuple.Create(true, Result.FAIL); //执行错误
  289. }
  290. timer.Start(timeout);
  291. state = STATE.WAIT;
  292. }
  293. bExecute = check();
  294. if (bExecute == null)
  295. {
  296. return Tuple.Create(true, Result.FAIL); //Termianate
  297. }
  298. if (bExecute.Value) //检查Success, next
  299. {
  300. next();
  301. return Tuple.Create(true, Result.RUN);
  302. }
  303. if (timer.IsTimeout())
  304. return Tuple.Create(true, Result.TIMEOUT);
  305. return Tuple.Create(true, Result.RUN);
  306. }
  307. return Tuple.Create(false, Result.RUN);
  308. }
  309. public Tuple<bool, Result> Wait<T>(T id, IRoutine rt)
  310. {
  311. int idx = Convert.ToInt32(id);
  312. bool bActive = Acitve(idx);
  313. if (bActive)
  314. {
  315. if (state == STATE.IDLE)
  316. {
  317. rt.Start();
  318. state = STATE.WAIT;
  319. }
  320. Result ret = rt.Monitor();
  321. return Tuple.Create(true, ret);
  322. }
  323. return Tuple.Create(false, Result.RUN);
  324. }
  325. //Monitor
  326. public Tuple<bool, Result> Monitor<T>(T id, Func<bool> func, Func<bool> check, double time)
  327. {
  328. int idx = Convert.ToInt32(id);
  329. bool bActive = Acitve(idx);
  330. bool bCheck = false;
  331. if (bActive)
  332. {
  333. if (state == STATE.IDLE)
  334. {
  335. if ((func != null) && !func())
  336. {
  337. return Tuple.Create(true, Result.FAIL);
  338. }
  339. timer.Start(time);
  340. state = STATE.WAIT;
  341. }
  342. bCheck = check();
  343. if (!bCheck)
  344. {
  345. return Tuple.Create(true, Result.FAIL); //Termianate
  346. }
  347. if (timer.IsTimeout())
  348. {
  349. next();
  350. }
  351. return Tuple.Create(true, Result.RUN);
  352. }
  353. return Tuple.Create(false, Result.RUN);
  354. }
  355. //Delay
  356. public Tuple<bool, Result> Delay<T>(T id, Func<bool> func, double time)
  357. {
  358. int idx = Convert.ToInt32(id);
  359. bool bActive = Acitve(idx);
  360. if (bActive)
  361. {
  362. if (state == STATE.IDLE)
  363. {
  364. if ((func != null) && !func())
  365. {
  366. return Tuple.Create(true, Result.FAIL);
  367. }
  368. timer.Start(time);
  369. state = STATE.WAIT;
  370. }
  371. if (timer.IsTimeout())
  372. {
  373. next();
  374. }
  375. return Tuple.Create(true, Result.RUN);
  376. }
  377. return Tuple.Create(false, Result.RUN);
  378. }
  379. //先delay 再运行
  380. public Tuple<bool, Result> DelayCheck<T>(T id, Func<bool> func, double time)
  381. {
  382. int idx = Convert.ToInt32(id);
  383. bool bActive = Acitve(idx);
  384. if (bActive)
  385. {
  386. if (state == STATE.IDLE)
  387. {
  388. timer.Start(time);
  389. state = STATE.WAIT;
  390. }
  391. if (timer.IsTimeout())
  392. {
  393. if (func != null && !func())
  394. {
  395. return Tuple.Create(true, Result.FAIL);
  396. }
  397. next();
  398. }
  399. return Tuple.Create(true, Result.RUN);
  400. }
  401. return Tuple.Create(false, Result.RUN);
  402. }
  403. #endregion
  404. private Tuple<bool,bool> execute(int id, Func<bool> func) //顺序执行
  405. {
  406. bool bActive = Acitve(id);
  407. bool bExecute = false;
  408. if (bActive)
  409. {
  410. bExecute = func();
  411. if (bExecute)
  412. {
  413. next();
  414. }
  415. }
  416. return Tuple.Create(bActive, bExecute);
  417. }
  418. private Tuple<bool, bool> Check(int id, Func<bool> func) //check
  419. {
  420. bool bActive = Acitve(id);
  421. bool bExecute = false;
  422. if (bActive)
  423. {
  424. bExecute = func();
  425. next();
  426. }
  427. return Tuple.Create(bActive, bExecute);
  428. }
  429. /// <summary>
  430. /// </summary>
  431. /// <param name="id"></param>
  432. /// <param name="func"></param>
  433. /// <param name="timeout"></param>
  434. /// <returns>
  435. /// item1 Active
  436. /// item2 execute
  437. /// item3 Timeout
  438. ///</returns>
  439. private Tuple<bool,bool, bool> wait(int id, Func<bool> func, double timeout = int.MaxValue) //Wait condition
  440. {
  441. bool bActive = Acitve(id);
  442. bool bExecute = false;
  443. bool bTimeout = false;
  444. if (bActive)
  445. {
  446. if (state == STATE.IDLE)
  447. {
  448. timer.Start(timeout);
  449. state = STATE.WAIT;
  450. }
  451. bExecute = func();
  452. if (bExecute)
  453. {
  454. next();
  455. }
  456. bTimeout = timer.IsTimeout();
  457. }
  458. return Tuple.Create(bActive, bExecute, bTimeout);
  459. }
  460. private Tuple<bool, bool?, bool> wait(int id, Func<bool?> func, double timeout = int.MaxValue) //Wait condition && Check error
  461. {
  462. bool bActive = Acitve(id);
  463. bool? bExecute = false;
  464. bool bTimeout = false;
  465. if (bActive)
  466. {
  467. if (state == STATE.IDLE)
  468. {
  469. timer.Start(timeout);
  470. state = STATE.WAIT;
  471. }
  472. bExecute = func();
  473. if (bExecute.HasValue && bExecute.Value)
  474. {
  475. next();
  476. }
  477. bTimeout = timer.IsTimeout();
  478. }
  479. return Tuple.Create(bActive, bExecute, bTimeout);
  480. }
  481. /// <summary>
  482. /// </summary>
  483. /// <param name="value"></param>
  484. /// <returns>
  485. /// item1 true, return item2
  486. /// </returns>
  487. private Tuple<bool,Result> Check(Tuple<bool, bool> value)
  488. {
  489. if (value.Item1)
  490. {
  491. if (!value.Item2)
  492. {
  493. return Tuple.Create(true, Result.FAIL);
  494. }
  495. return Tuple.Create(true, Result.RUN);
  496. }
  497. return Tuple.Create(false, Result.RUN);
  498. }
  499. private Tuple<bool, Result> Check(Tuple<bool, bool, bool> value)
  500. {
  501. if (value.Item1) // 当前执行
  502. {
  503. if (CheckTimeout(value)) //timeout
  504. {
  505. return Tuple.Create(true, Result.TIMEOUT);
  506. }
  507. return Tuple.Create(true, Result.RUN);
  508. }
  509. return Tuple.Create(false, Result.RUN);
  510. }
  511. private Tuple<bool, Result> Check(Tuple<bool, bool?, bool> value)
  512. {
  513. if (value.Item1) // 当前执行
  514. {
  515. if (value.Item2 == null)
  516. {
  517. return Tuple.Create(true, Result.FAIL);
  518. }
  519. else
  520. {
  521. if (value.Item2 == false && value.Item3 == true) //timeout
  522. {
  523. return Tuple.Create(true, Result.TIMEOUT);
  524. }
  525. return Tuple.Create(true, Result.RUN);
  526. }
  527. }
  528. return Tuple.Create(false, Result.RUN);
  529. }
  530. private bool CheckTimeout(Tuple<bool, bool, bool> value)
  531. {
  532. return value.Item1 == true && value.Item2 == false && value.Item3 == true;
  533. }
  534. private bool Acitve(int id) //
  535. {
  536. if (_steps.Contains(id))
  537. return false;
  538. this._id = id;
  539. return true;
  540. }
  541. private void next()
  542. {
  543. if(!IsCurrentStepExcuteFailed)
  544. _steps.Push(this._id);
  545. state = STATE.IDLE;
  546. }
  547. private void next(int step) //loop
  548. {
  549. while(_steps.Pop() != step);
  550. state = STATE.IDLE;
  551. }
  552. public void Delay(int id, double delaySeconds)
  553. {
  554. Tuple<bool, Result> ret = Delay(id, () =>
  555. {
  556. return true;
  557. }, delaySeconds * 1000);
  558. if (ret.Item1)
  559. {
  560. if (ret.Item2 == Result.RUN)
  561. {
  562. throw (new RoutineBreakException());
  563. }
  564. }
  565. }
  566. public bool IsActived(int id)
  567. {
  568. return _steps.Contains(id);
  569. }
  570. public void RetryCurrentStep(int step)
  571. {
  572. if (_steps.Contains(step))
  573. {
  574. _steps.Pop();
  575. }
  576. IsCurrentStepExcuteFailed = true;
  577. }
  578. public void StartRetry()
  579. {
  580. IsCurrentStepExcuteFailed = false;
  581. state = STATE.IDLE;
  582. }
  583. public void PauseRountine(bool isPause)
  584. {
  585. if (isPause && !timer.IsIdle())//暂停
  586. {
  587. _pauseTime = timer.GetTotalTime();
  588. timer.Stop();
  589. }
  590. if (!isPause && timer.IsIdle())
  591. {
  592. if (_pauseTime > 0)
  593. {
  594. timer.Start(_pauseTime);
  595. }
  596. }
  597. }
  598. }
  599. public class ModuleRoutine : SeqenecRoutine
  600. {
  601. protected bool _isHasAlarm = false;
  602. public string Module { get; set; }
  603. public string Name { get; set; }
  604. public string StepName
  605. {
  606. get
  607. {
  608. return _stepName;
  609. }
  610. }
  611. protected string _stepName;
  612. public TimeSpan StepLeftTime
  613. {
  614. get
  615. {
  616. if (_stepSpan.TotalMilliseconds < 1)
  617. return _stepSpan;
  618. return (_stepSpan - (DateTime.Now - _stepStartTime));
  619. }
  620. }
  621. protected TimeSpan _stepSpan = new TimeSpan(0, 0, 0, 0);
  622. protected DateTime _stepStartTime;
  623. public delegate RoutineState RoutineFunc<T>(T arg);
  624. protected Result RoutineStepResult { get; set; }
  625. protected void Notify(string message)
  626. {
  627. EV.PostInfoLog(Module, $"{Module} {Name}, {message}");
  628. }
  629. protected void Stop(string failReason)
  630. {
  631. EV.PostAlarmLog(Module, $"{Module} {Name} failed, {failReason}");
  632. }
  633. private static object locker=new object();
  634. public void Abort(string failReason)
  635. {
  636. //lock (locker)
  637. //{
  638. //Thread.Sleep(500);
  639. EV.PostAlarmLog(Module, $"{Module} {Name} {failReason}");
  640. //}
  641. }
  642. public void TimeDelay(int id, string stepName, double time)
  643. {
  644. Tuple<bool, Result> ret = Delay(id, () =>
  645. {
  646. Notify($"Delay {time} seconds");
  647. _stepSpan = new TimeSpan(0, 0, 0, (int)time);
  648. _stepStartTime = DateTime.Now;
  649. _stepName = stepName;
  650. return true;
  651. }, time * 1000);
  652. if (ret.Item1)
  653. {
  654. if (ret.Item2 == Result.RUN)
  655. {
  656. throw (new RoutineBreakException());
  657. }
  658. }
  659. }
  660. public void TimeDelay(int id, double time)
  661. {
  662. Tuple<bool, Result> ret = Delay(id, () =>
  663. {
  664. Notify($"Delay {time} seconds");
  665. _stepSpan = new TimeSpan(0,0,0,(int)time);
  666. _stepStartTime = DateTime.Now;
  667. return true;
  668. }, time * 1000);
  669. if (ret.Item1)
  670. {
  671. if (ret.Item2 == Result.RUN)
  672. {
  673. throw (new RoutineBreakException());
  674. }
  675. }
  676. }
  677. protected void ExecuteRoutine(int id, IRoutine routine)
  678. {
  679. Tuple<bool, Result> ret = ExecuteAndWait(id, routine);
  680. if (ret.Item1)
  681. {
  682. if (ret.Item2 == Result.FAIL)
  683. {
  684. throw (new RoutineFaildException());
  685. }
  686. else if (ret.Item2 == Result.RUN)
  687. {
  688. throw (new RoutineBreakException());
  689. }
  690. }
  691. }
  692. protected void PerformStep<T, T1>(T step, RoutineFunc<T1> func, T1 param1)
  693. {
  694. int idx = Convert.ToInt32(step);
  695. RoutineState state = func(param1);
  696. }
  697. public void Loop(int id, int count)
  698. {
  699. Tuple<bool, Result> ret = Loop(id, () =>
  700. {
  701. Notify($"Start loop {LoopCounter+1}/{count}");
  702. return true;
  703. }, count);
  704. if (ret.Item1)
  705. {
  706. if (ret.Item2 == Result.FAIL)
  707. throw new RoutineFaildException();
  708. }
  709. }
  710. public void EndLoop(int id)
  711. {
  712. Tuple<bool, Result> ret = EndLoop(id, () =>
  713. {
  714. Notify($"Loop finished");
  715. return true;
  716. });
  717. if (ret.Item1)
  718. {
  719. throw new RoutineBreakException();
  720. }
  721. }
  722. public virtual Result Monitor()
  723. {
  724. RoutineStart();
  725. MonitorStep();
  726. RoutineStop();
  727. return RoutineStepResult;
  728. }
  729. protected virtual void MonitorStep()
  730. {
  731. }
  732. protected void RoutineStart()
  733. {
  734. if (_historySteps.Count == 0 && TokenId == -1)
  735. {
  736. LOG.Write($"{Module}.{Name} begin");
  737. RoutineStepResult = Result.RUN;
  738. }
  739. }
  740. protected void RoutineStop()
  741. {
  742. if (_waitSteps.Count == 0 && _historySteps.Contains(TokenId) && RoutineStepResult == Result.RUN)
  743. {
  744. RoutineStepResult = Result.DONE;
  745. LOG.Write($"{Module}.{Name} end");
  746. }
  747. }
  748. }
  749. public class QueueRoutine
  750. {
  751. private Queue< IRoutine > _steps = new Queue< IRoutine >();
  752. private IRoutine _currentStep = null;
  753. public void Add(IRoutine step)
  754. {
  755. _steps.Enqueue(step);
  756. }
  757. public void Reset()
  758. {
  759. _steps.Clear();
  760. _currentStep = null;
  761. }
  762. public void Abort()
  763. {
  764. if (_currentStep != null)
  765. _currentStep.Abort();
  766. Reset();
  767. }
  768. public Result Start(params object[] objs)
  769. {
  770. if (_steps.Count == 0)
  771. return Result.DONE;
  772. _currentStep = _steps.Dequeue();
  773. return _currentStep.Start(objs);
  774. }
  775. public Result Monitor(params object[] objs)
  776. {
  777. Result ret = Result.FAIL;
  778. if (_currentStep != null)
  779. {
  780. ret = _currentStep.Monitor();
  781. }
  782. if (ret == Result.DONE)
  783. {
  784. _currentStep = _steps.Count > 0 ? _steps.Dequeue() : null;
  785. if (_currentStep != null)
  786. {
  787. return _currentStep.Start(objs);
  788. }
  789. }
  790. return ret;
  791. }
  792. }
  793. }