WaferHolderTask.cs 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. using Aitex.Core.RT.Log;
  2. using Aitex.Core.Util;
  3. using MECF.Framework.Common.Equipment;
  4. using MECF.Framework.Common.SubstrateTrackings;
  5. using MECF.Framework.Common.WaferHolder;
  6. using CyberX8_Core;
  7. using CyberX8_RT.Modules.Loader;
  8. using CyberX8_RT.Modules.PUF;
  9. using CyberX8_RT.Modules;
  10. using CyberX8_RT.Schedulers;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.ComponentModel;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. using System.Windows.Documents;
  18. using Aitex.Core.Common;
  19. using MECF.Framework.Common.CommonData;
  20. using MECF.Framework.Common.Jobs;
  21. using Aitex.Core.RT.Fsm;
  22. using MECF.Framework.Common.RecipeCenter;
  23. using MECF.Framework.Common.ToolLayout;
  24. using Aitex.Core.RT.Routine;
  25. using CyberX8_RT.Schedulers.Transporter;
  26. using CyberX8_RT.Modules.Rinse;
  27. namespace CyberX8_RT.Dispatch
  28. {
  29. public enum WaferHolderTaskState
  30. {
  31. Created,
  32. Processing,
  33. End,
  34. Error,
  35. Canceled
  36. }
  37. /// <summary>
  38. /// WaferHolder
  39. /// </summary>
  40. /// <param name="info"></param>
  41. /// <param name="schedulerSequence"></param>
  42. public delegate void WaferHolderSchedulerComplete(WaferHolderInfo info, SchedulerSequence schedulerSequence);
  43. /// <summary>
  44. /// WaferHolderTask完成
  45. /// </summary>
  46. /// <param name="id"></param>
  47. public delegate void WaferHolderTaskComplete(string id);
  48. public class WaferHolderTask
  49. {
  50. #region 常量
  51. private const string PWT = "PWT";
  52. #endregion
  53. #region 内部变量
  54. /// <summary>
  55. /// 调度步骤
  56. /// </summary>
  57. private List<SchedulerSequence> _schedulerSequences;
  58. /// <summary>
  59. /// 当前步骤索引
  60. /// </summary>
  61. private int _currentSequenceIndex = 0;
  62. /// <summary>
  63. /// PUF实例
  64. /// </summary>
  65. private PUFEntity _puf1Entity;
  66. /// <summary>
  67. /// PUF实例
  68. /// </summary>
  69. private PUFEntity _puf2Entity;
  70. /// <summary>
  71. /// 是否开始执行
  72. /// </summary>
  73. private bool _isStart = false;
  74. /// <summary>
  75. /// 暂停时的索引
  76. /// </summary>
  77. private int _pausedIndex = -1;
  78. /// <summary>
  79. /// 错误上升触发
  80. /// </summary>
  81. private R_TRIG _sequenceErrorTigger = new R_TRIG();
  82. /// <summary>
  83. /// Sequence类型
  84. /// </summary>
  85. private string _sequenceType = "";
  86. /// <summary>
  87. /// FA回复
  88. /// </summary>
  89. private SchedulerFACallback _schedulerFACallback = new SchedulerFACallback();
  90. #endregion
  91. #region 属性
  92. /// <summary>
  93. /// ID
  94. /// </summary>
  95. public string ID { get;private set; }
  96. /// <summary>
  97. /// WaferHolder属性
  98. /// </summary>
  99. public WaferHolderInfo WaferHolderInfo { get;private set; }
  100. /// <summary>
  101. /// Process Job信息
  102. /// </summary>
  103. public ProcessJobInfo ProcessJobInfo { get;private set; }
  104. /// <summary>
  105. /// 状态
  106. /// </summary>
  107. public WaferHolderTaskState State { get; private set; }
  108. /// <summary>
  109. /// 步骤完成事件
  110. /// </summary>
  111. public event WaferHolderSchedulerComplete OnSchedulerComplete;
  112. /// <summary>
  113. /// 任务完成事件
  114. /// </summary>
  115. public event WaferHolderTaskComplete OnTaskComplete;
  116. /// <summary>
  117. /// 调度集合
  118. /// </summary>
  119. public List<SchedulerSequence> SchedulerSequences { get { return _schedulerSequences; } }
  120. #endregion
  121. /// <summary>
  122. /// 构造函数
  123. /// </summary>
  124. /// <param name="waferHolderInfo"></param>
  125. /// <param name="schedulerSequences"></param>
  126. public WaferHolderTask(WaferHolderInfo waferHolderInfo,ProcessJobInfo processJobInfo)
  127. {
  128. ID=Guid.NewGuid().ToString();
  129. WaferHolderInfo=waferHolderInfo;
  130. WaferHolderInfo.Status = WaferHolderStatus.Normal;
  131. if (processJobInfo != null)
  132. {
  133. WaferHolderInfo.SequenceId = processJobInfo.SequenceRecipe.Ppid;
  134. WaferHolderInfo.SequenceRecipe = processJobInfo.SequenceRecipe;
  135. _sequenceType = processJobInfo.SequenceRecipe.SequenceType;
  136. WaferHolderInfo.CurrentControlJobId = processJobInfo.ControlJobName;
  137. WaferHolderInfo.LotId = processJobInfo.LotName;
  138. }
  139. else
  140. {
  141. AnalyseProductionProcessJobInfo();
  142. }
  143. ProcessJobInfo=processJobInfo;
  144. State = WaferHolderTaskState.Created;
  145. _puf1Entity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(ModuleName.PUF1.ToString());
  146. _puf2Entity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(ModuleName.PUF2.ToString());
  147. }
  148. /// <summary>
  149. /// 初始化调度步骤
  150. /// </summary>
  151. /// <param name="schedulers"></param>
  152. public void InitialSchedulers(List<SchedulerSequence> schedulers)
  153. {
  154. _schedulerSequences = schedulers;
  155. }
  156. /// <summary>
  157. /// 分析生产片的ProcessJob信息
  158. /// </summary>
  159. private void AnalyseProductionProcessJobInfo()
  160. {
  161. if (!string.IsNullOrEmpty(WaferHolderInfo.WaferAId))
  162. {
  163. WaferInfo waferAInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferAId);
  164. if (waferAInfo != null && waferAInfo.WaferType == WaferType.Production)
  165. {
  166. ProcessJobInfo = waferAInfo.ProcessJob;
  167. _sequenceType = ProcessJobInfo.SequenceRecipe.SequenceType;
  168. WaferHolderInfo.CurrentControlJobId = ProcessJobInfo.ControlJobName;
  169. WaferHolderInfo.LotId = ProcessJobInfo.LotName;
  170. WaferHolderInfo.SequenceRecipe = ProcessJobInfo.SequenceRecipe;
  171. return;
  172. }
  173. }
  174. if (!string.IsNullOrEmpty(WaferHolderInfo.WaferBId))
  175. {
  176. WaferInfo waferBInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferBId);
  177. if (waferBInfo != null && waferBInfo.WaferType == WaferType.Production)
  178. {
  179. ProcessJobInfo = waferBInfo.ProcessJob;
  180. _sequenceType = ProcessJobInfo.SequenceRecipe.SequenceType;
  181. WaferHolderInfo.CurrentControlJobId = ProcessJobInfo.ControlJobName;
  182. WaferHolderInfo.LotId = ProcessJobInfo.LotName;
  183. WaferHolderInfo.SequenceRecipe = ProcessJobInfo.SequenceRecipe;
  184. }
  185. }
  186. }
  187. /// <summary>
  188. /// 执行
  189. /// </summary>
  190. public void Run()
  191. {
  192. if(_currentSequenceIndex>=_schedulerSequences.Count)
  193. {
  194. State = WaferHolderTaskState.End;
  195. if(OnTaskComplete!=null)
  196. {
  197. OnTaskComplete(ID);
  198. }
  199. FaModuleNotifier.Instance.NotifyWaferShuttleJobEnd(WaferHolderInfo);
  200. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"WaferHolder {WaferHolderInfo.Id} task complete");
  201. return;
  202. }
  203. if (!_isStart)
  204. {
  205. bool preCondition = CheckStartCondition();
  206. if (!preCondition)
  207. {
  208. return;
  209. }
  210. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} prepare Start {_currentSequenceIndex + 1} sequence");
  211. _isStart = true;
  212. if (WaferHolderInfo.SchedulerModules == null)
  213. {
  214. WaferHolderInfo.SchedulerModules = new List<string>();
  215. }
  216. WaferHolderInfo.SchedulerModules.Clear();
  217. }
  218. SchedulerSequence sequence = _schedulerSequences[_currentSequenceIndex];
  219. //暂停中
  220. if (sequence.State == RState.Init && _currentSequenceIndex >= _pausedIndex && _pausedIndex != -1)
  221. {
  222. return;
  223. }
  224. if (_currentSequenceIndex == _schedulerSequences.Count - 1 && sequence.State == RState.End)
  225. {
  226. State=WaferHolderTaskState.End;
  227. if (OnTaskComplete != null)
  228. {
  229. OnTaskComplete(ID);
  230. }
  231. FaModuleNotifier.Instance.NotifyWaferShuttleJobEnd(WaferHolderInfo);
  232. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"WaferHolder {WaferHolderInfo.Id} task complete");
  233. return;
  234. }
  235. if(_currentSequenceIndex<_schedulerSequences.Count)
  236. {
  237. if(sequence.State==RState.Init)
  238. {
  239. if(sequence.SchedulerModule==null)
  240. {
  241. return;
  242. }
  243. if(!BufferWaferHolderJudgeResource(sequence))
  244. {
  245. return;
  246. }
  247. string reason = "";
  248. bool sequeceCondition = sequence.SchedulerModule.CheckPrecondition(_schedulerSequences, _currentSequenceIndex, sequence.Parameters,WaferHolderInfo.Id,ref reason);
  249. if (sequeceCondition)
  250. {
  251. bool result = sequence.SchedulerModule.RunProcess(sequence.Recipe,sequence.Parameters, sequence.SynchronousModuleMessages);
  252. if (result)
  253. {
  254. if (State == WaferHolderTaskState.Created)
  255. {
  256. State = WaferHolderTaskState.Processing;
  257. FaModuleNotifier.Instance.NotifyWaferShuttleJobStart(WaferHolderInfo);
  258. }
  259. sequence.State = RState.Running;
  260. sequence.StartTime = DateTime.Now;
  261. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} Start {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module}");
  262. }
  263. else
  264. {
  265. if (sequence.ModuleName == ModuleName.Transporter1&&sequence.NextModuleType==ModuleType.Metal)
  266. {
  267. if (!CheckAfterMetalAvaible())
  268. {
  269. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} has no avaible metal");
  270. TransporterAction action = sequence.Parameters as TransporterAction;
  271. if (action.ActionMsg == Modules.Transporter.TransporterMSG.Transfer)
  272. {
  273. WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;
  274. waferHolderMoveItem.DestModuleType = ModuleType.Dryer;
  275. waferHolderMoveItem.DestModule = ModuleName.Unknown;
  276. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} next sequence changed to dryer");
  277. }
  278. }
  279. }
  280. }
  281. }
  282. else
  283. {
  284. _sequenceErrorTigger.CLK = !sequeceCondition;
  285. if (_sequenceErrorTigger.Q)
  286. {
  287. LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferHolderInfo.Id} Start {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} failed,{reason}");
  288. }
  289. }
  290. }
  291. else if(sequence.State==RState.Running)
  292. {
  293. sequence.SchedulerModule.MonitorProcess(sequence,false);
  294. _sequenceErrorTigger.CLK = sequence.SchedulerModule.IsError;
  295. if (sequence.SchedulerModule.IsError)
  296. {
  297. //用于LoadTransporter取的WaferHolder Id不一致,则取消当前WaferHolderTask
  298. if (sequence.ModuleName == ModuleName.Transporter2)
  299. {
  300. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} failed,task canceled");
  301. State = WaferHolderTaskState.Canceled;
  302. return;
  303. }
  304. if (_sequenceErrorTigger.Q)
  305. {
  306. AnalyseSchedulerErrorState(sequence);
  307. }
  308. }
  309. else if(sequence.SchedulerModule.IsIdle)
  310. {
  311. sequence.EndTime = DateTime.Now;
  312. sequence.State = RState.End;
  313. sequence.ProcessMilliSeconds=sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;
  314. if(sequence.IsProcessSequece)
  315. {
  316. UpdateWaferHolderProcessingStatus();
  317. }
  318. if(sequence.IsLastProcessSequence)
  319. {
  320. UpdateWaferHolderProcessComplete();
  321. }
  322. if (OnSchedulerComplete != null)
  323. {
  324. OnSchedulerComplete(WaferHolderInfo, sequence);
  325. }
  326. UpdateLoaderToBufferWaferHolderToloaderStatus(sequence);
  327. LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.ModuleName} complete, time length {sequence.ProcessMilliSeconds}");
  328. _currentSequenceIndex++;
  329. AutoChangeLoaderTransporterScheduler();
  330. //检验rinse后面是否存在可用的Metal
  331. if (sequence.ModuleType == ModuleType.Rinse)
  332. {
  333. AnalyseRinseAfterMetalAvaible(sequence);
  334. }
  335. else if (sequence.ModuleType == ModuleType.Prewet)
  336. {
  337. AnalysePrewetAfterMetalAvaible(sequence);
  338. }
  339. }
  340. }
  341. else if (sequence.State == RState.End)
  342. {
  343. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence is End");
  344. _currentSequenceIndex++;
  345. }
  346. }
  347. }
  348. /// <summary>
  349. /// 更新任务结束
  350. /// </summary>
  351. public void UpdateDryerLastSchedulerComplete()
  352. {
  353. SchedulerSequence sequence = _schedulerSequences[_currentSequenceIndex];
  354. sequence.EndTime = DateTime.Now;
  355. sequence.State = RState.End;
  356. sequence.ProcessMilliSeconds = sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;
  357. LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferHolderInfo.Id} {_currentSequenceIndex+1} sequence {sequence.ModuleName} complete, time length {sequence.ProcessMilliSeconds}");
  358. State = WaferHolderTaskState.End;
  359. if (OnTaskComplete != null)
  360. {
  361. OnTaskComplete(ID);
  362. }
  363. LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"WaferHolder {WaferHolderInfo.Id} task complete");
  364. }
  365. /// <summary>
  366. /// 更新从Loader到Buffer的WaferHolder更新为不可以拉回至Loader
  367. /// </summary>
  368. /// <param name="sequence"></param>
  369. private void UpdateLoaderToBufferWaferHolderToloaderStatus(SchedulerSequence sequence)
  370. {
  371. string currentLocation = WaferHolderInfo.CurrentLocation;
  372. if(!Enum.TryParse(currentLocation,out ModuleName locationName))
  373. {
  374. return;
  375. }
  376. if (!ModuleHelper.IsBuffer(locationName))
  377. {
  378. return;
  379. }
  380. if (sequence.ModuleName == ModuleName.Transporter2)
  381. {
  382. TransporterAction transporterAction = sequence.Parameters as TransporterAction;
  383. if (transporterAction.ActionMsg == Modules.Transporter.TransporterMSG.Transfer)
  384. {
  385. WaferHolderMoveItem waferHolderMoveItem = transporterAction.Parameter as WaferHolderMoveItem;
  386. if (waferHolderMoveItem.SourceModule == ModuleName.Loader1 && waferHolderMoveItem.DestModuleType == ModuleType.Buffer)
  387. {
  388. WaferHolderInfo.IsToLoader = false;
  389. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} IsToLoader Changed to false;");
  390. }
  391. else if (waferHolderMoveItem.DestModuleType == ModuleType.Buffer && waferHolderMoveItem.SourceModuleType != ModuleType.Loader)
  392. {
  393. WaferHolderInfo.IsToLoader = true;
  394. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} IsToLoader Changed to true;");
  395. }
  396. }
  397. }
  398. }
  399. /// <summary>
  400. /// 分析错误状态下的调度
  401. /// </summary>
  402. private void AnalyseSchedulerErrorState(SchedulerSequence sequence)
  403. {
  404. if (sequence.ModuleType == ModuleType.Prewet)
  405. {
  406. AnalyseSchedulerPrewetErrorState(sequence);
  407. }
  408. else if (sequence.ModuleType == ModuleType.Dryer)
  409. {
  410. AnalyseSchedulerDryerErrorState(sequence);
  411. }
  412. else if (sequence.ModuleType == ModuleType.Rinse)
  413. {
  414. RinseItem rinseItem = RinseItemManager.Instance.GetRinseItem(sequence.ModuleName.ToString());
  415. if (rinseItem == null)
  416. {
  417. return;
  418. }
  419. if (rinseItem.SubType != PWT)
  420. {
  421. AnalyseSchedulerRinseErrorState(sequence);
  422. }
  423. else
  424. {
  425. AnalyseSchedulerPrewetErrorState(sequence);
  426. }
  427. }
  428. else if (sequence.ModuleType == ModuleType.Metal)
  429. {
  430. AnalyseSchedulerMetalErrorState(sequence);
  431. }
  432. }
  433. /// <summary>
  434. /// 判定Buffer中WaferHolder的后面工序是否存在可用资源,不存在的话,则Task直接结束
  435. /// </summary>
  436. /// <param name="sequence"></param>
  437. private bool BufferWaferHolderJudgeResource(SchedulerSequence sequence)
  438. {
  439. string currentLocation = WaferHolderInfo.CurrentLocation;
  440. if (Enum.TryParse(currentLocation, out ModuleName moduleName))
  441. {
  442. //当前WaferHolder处于Buffer中,当前步骤不是第一步,当前调度模块为transporter2
  443. if (ModuleHelper.IsBuffer(moduleName)&&_currentSequenceIndex!=0&&sequence.ModuleName==ModuleName.Transporter2)
  444. {
  445. if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(WaferHolderInfo.SequenceRecipe, false))
  446. {
  447. for (int i = _currentSequenceIndex; i < _schedulerSequences.Count; i++)
  448. {
  449. SchedulerSequence item = _schedulerSequences[i];
  450. item.State = RState.End;
  451. }
  452. _currentSequenceIndex = _schedulerSequences.Count - 1;
  453. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} exist no avaible cell");
  454. WaferHolderInfo.IsToLoader = true;
  455. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} IsToLoader Changed to true");
  456. RemoveWaferHolderSRDScheduler();
  457. UpdateWaferHolderMisProcessedStatus();
  458. return false;
  459. }
  460. }
  461. }
  462. return true;
  463. }
  464. /// <summary>
  465. /// 检验Prewet后面的Metal是否存在可用
  466. /// </summary>
  467. private void AnalysePrewetAfterMetalAvaible(SchedulerSequence schedulerSequence)
  468. {
  469. //获取可用的Metal以及Rinse
  470. if (!CheckAfterMetalAvaible())
  471. {
  472. LOG.WriteLog(eEvent.WARN_SCHEDULER, "System", $"{WaferHolderInfo.Id} has no avaible metal after prewet");
  473. SkipAfterMetal(schedulerSequence,true);
  474. RemoveWaferHolderSRDScheduler();
  475. UpdateWaferHolderMisProcessedStatus();
  476. //SchedulerSequence nextSchedulerSequence = _schedulerSequences[_currentSequenceIndex];
  477. //if (nextSchedulerSequence.ModuleName != ModuleName.Transporter1)
  478. //{
  479. // return;
  480. //}
  481. //WaferHolderMoveItem waferHolderMoveItem = nextSchedulerSequence.Parameters as WaferHolderMoveItem;
  482. //waferHolderMoveItem.DestModuleType = ModuleType.Dryer;
  483. //waferHolderMoveItem.DestModule = ModuleName.Unknown;
  484. }
  485. }
  486. /// <summary>
  487. /// 检验Rinse后面的Metal是否存在可用
  488. /// </summary>
  489. /// <returns></returns>
  490. private void AnalyseRinseAfterMetalAvaible(SchedulerSequence schedulerSequence)
  491. {
  492. //获取可用的Metal以及Rinse
  493. if(!CheckAfterMetalAvaible())
  494. {
  495. LOG.WriteLog(eEvent.WARN_SCHEDULER, "System", $"{WaferHolderInfo.Id} has no avaible metal after rinse");
  496. SkipAfterMetal(schedulerSequence,true);
  497. RemoveWaferHolderSRDScheduler();
  498. UpdateWaferHolderMisProcessedStatus();
  499. }
  500. }
  501. /// <summary>
  502. /// 检验后续Metal可用性
  503. /// </summary>
  504. /// <returns></returns>
  505. private bool CheckAfterMetalAvaible()
  506. {
  507. for (int i = _currentSequenceIndex + 1; i < _schedulerSequences.Count; i++)
  508. {
  509. SchedulerSequence sequence = _schedulerSequences[i];
  510. if (sequence.ModuleType != ModuleType.Metal)
  511. {
  512. continue ;
  513. }
  514. if (sequence.Recipe == null || !(sequence.Recipe is DepRecipe))
  515. {
  516. continue;
  517. }
  518. DepRecipe depRecipe = (DepRecipe)sequence.Recipe;
  519. bool result= SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, sequence.SequenceType,sequence.WaferSize);
  520. if (!result)
  521. {
  522. return false;
  523. }
  524. }
  525. return true;
  526. }
  527. #region Analyse ErrorState Scheduler
  528. /// <summary>
  529. /// Prewet出错重新调度
  530. /// </summary>
  531. /// <param name="sequence"></param>
  532. private void AnalyseSchedulerPrewetErrorState(SchedulerSequence sequence)
  533. {
  534. SkipAfterSchedulerToDry(ModuleName.Transporter2);
  535. sequence.State = RState.End;
  536. sequence.EndTime = DateTime.Now;
  537. sequence.ProcessMilliSeconds= sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;
  538. RemoveWaferHolderSRDScheduler();
  539. UpdateWaferHolderMisProcessedStatus();
  540. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Prewet meet error,scheduler changed to transporter2");
  541. }
  542. /// <summary>
  543. /// 路过后面调度直接至Dryer
  544. /// </summary>
  545. private void SkipAfterSchedulerToDry(ModuleName transporterName)
  546. {
  547. for (int i = _currentSequenceIndex=1; i < _schedulerSequences.Count; i++)
  548. {
  549. SchedulerSequence item = _schedulerSequences[i];
  550. if (item.ModuleName != ModuleName.Transporter1)
  551. {
  552. item.State = RState.End;
  553. item.ProcessMilliSeconds = 0;
  554. }
  555. else
  556. {
  557. if (item.Parameters is TransporterAction)
  558. {
  559. TransporterAction action= (TransporterAction)item.Parameters;
  560. if (action.ActionMsg == Modules.Transporter.TransporterMSG.Transfer)
  561. {
  562. WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;
  563. if (waferHolderMoveItem.DestModuleType == ModuleType.Dryer)
  564. {
  565. _currentSequenceIndex = i;
  566. item.SchedulerModule = SchedulerManager.Instance.GetScheduler(transporterName);
  567. waferHolderMoveItem.SourceModule = ModuleName.Prewet1;
  568. waferHolderMoveItem.SourceModuleType = ModuleType.Prewet;
  569. break;
  570. }
  571. else
  572. {
  573. item.State = RState.End;
  574. item.ProcessMilliSeconds = 0;
  575. }
  576. }
  577. }
  578. }
  579. }
  580. }
  581. /// <summary>
  582. /// Dryer出错重新调度,上一步调度修改为transporter2,同时tranporter2搬运源目标为当前Module,目标类型也是Dryer
  583. /// </summary>
  584. /// <param name="sequence"></param>
  585. private void AnalyseSchedulerDryerErrorState(SchedulerSequence sequence)
  586. {
  587. if (SchedulerSequenceManager.Instance.GetAvaibleModuleCell(_sequenceType,ModuleType.Dryer)!=ModuleName.Unknown)
  588. {
  589. sequence.State = RState.Init;
  590. SchedulerSequence preSchedulerSequence = GetPreSchedulerSequence();
  591. preSchedulerSequence.State = RState.Init;
  592. preSchedulerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Transporter2);
  593. TransporterAction action = preSchedulerSequence.Parameters as TransporterAction;
  594. if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)
  595. {
  596. return;
  597. }
  598. WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;
  599. waferHolderMoveItem.SourceModule = waferHolderMoveItem.DestModule;
  600. waferHolderMoveItem.SourceModuleType = waferHolderMoveItem.DestModuleType;
  601. waferHolderMoveItem.DestModuleType = waferHolderMoveItem.DestModuleType;
  602. waferHolderMoveItem.DestModule = ModuleName.Unknown;
  603. sequence.SchedulerModule = null;
  604. _currentSequenceIndex--;
  605. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Dryer meet error,rescheduler changed to transporter2");
  606. }
  607. else
  608. {
  609. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Dryer meet error,rescheduler has no avaible dryer");
  610. }
  611. }
  612. /// <summary>
  613. /// Rinse出错重新调度,回退至上一步调度
  614. /// </summary>
  615. /// <param name="sequence"></param>
  616. private void AnalyseSchedulerRinseErrorState(SchedulerSequence sequence)
  617. {
  618. ModuleName metalName = SchedulerSequenceManager.Instance.GetPreMetalModuleName(_currentSequenceIndex, _schedulerSequences);
  619. if (metalName == ModuleName.Unknown)
  620. {
  621. return;
  622. }
  623. if (SchedulerSequenceManager.Instance.GetAvaibleModuleCell(_sequenceType, ModuleType.Rinse,metalName) != ModuleName.Unknown)
  624. {
  625. sequence.State = RState.Init;
  626. SchedulerSequence preSchedulerSequence = GetPreSchedulerSequence();
  627. preSchedulerSequence.State = RState.Init;
  628. TransporterAction action = preSchedulerSequence.Parameters as TransporterAction;
  629. if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)
  630. {
  631. return;
  632. }
  633. WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;
  634. waferHolderMoveItem.SourceModule = waferHolderMoveItem.DestModule;
  635. waferHolderMoveItem.SourceModuleType = waferHolderMoveItem.DestModuleType;
  636. waferHolderMoveItem.DestModuleType = waferHolderMoveItem.DestModuleType;
  637. waferHolderMoveItem.DestModule = ModuleName.Unknown;
  638. sequence.SchedulerModule = null;
  639. _currentSequenceIndex--;
  640. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Rinse meet error,scheduler changed to transporter1");
  641. }
  642. else
  643. {
  644. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Rinse meet error,rescheduler has no avaible rinse");
  645. }
  646. }
  647. /// <summary>
  648. /// Metal出错重新调度,回退至上一步调度
  649. /// </summary>
  650. /// <param name="sequence"></param>
  651. private void AnalyseSchedulerMetalErrorState(SchedulerSequence sequence)
  652. {
  653. //当前步骤结束,WaferHolder状态
  654. UpdateWaferHolderErrorStatus();
  655. sequence.EndTime = DateTime.Now;
  656. sequence.ProcessMilliSeconds= sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;
  657. sequence.State = RState.End;
  658. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Metal meet error,rescheduler changed to next module");
  659. //跳过后面的metal
  660. SkipAfterMetal(sequence,false);
  661. //移除SRD调度
  662. RemoveWaferHolderSRDScheduler();
  663. _currentSequenceIndex++;
  664. }
  665. /// <summary>
  666. /// 跳过后面的Metal
  667. /// </summary>
  668. private void SkipAfterMetal(SchedulerSequence schedulerSequence,bool isSetLastSequenceSourceModule)
  669. {
  670. int startIndex = -1;
  671. int endIndex = -1;
  672. //从下一个Metal直到碰到Dryer
  673. for (int i = _currentSequenceIndex + 1; i < _schedulerSequences.Count; i++)
  674. {
  675. SchedulerSequence item = _schedulerSequences[i];
  676. if (item.ModuleType == ModuleType.Metal && startIndex == -1)
  677. {
  678. startIndex = i;
  679. }
  680. if (item.ModuleType == ModuleType.Dryer)
  681. {
  682. endIndex = i - 1;//Dryer前一步骤为Transporter,保留Dryer前面的transporter
  683. break;
  684. }
  685. }
  686. //将后面的Metal的步骤直接跳过,包含gh g 后面的transporter
  687. if (startIndex != -1)
  688. {
  689. for (int i = startIndex - 1; i < endIndex; i++)
  690. {
  691. SchedulerSequence item = _schedulerSequences[i];
  692. item.State = RState.End;
  693. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} skip {i+1} sequence {item.ModuleType}");
  694. }
  695. }
  696. //是否设置最后调度的源模块
  697. if (isSetLastSequenceSourceModule)
  698. {
  699. SchedulerSequence lastSchedulerSequence = _schedulerSequences[endIndex];
  700. if (lastSchedulerSequence.ModuleType == ModuleType.Transporter)
  701. {
  702. TransporterAction action = lastSchedulerSequence.Parameters as TransporterAction;
  703. if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)
  704. {
  705. return;
  706. }
  707. WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;
  708. if (schedulerSequence.SchedulerModule != null)
  709. {
  710. waferHolderMoveItem.SourceModule = schedulerSequence.ModuleName;
  711. waferHolderMoveItem.SourceModuleType = schedulerSequence.ModuleType;
  712. }
  713. }
  714. }
  715. }
  716. /// <summary>
  717. /// 移除SRD调度
  718. /// </summary>
  719. private void RemoveWaferHolderSRDScheduler()
  720. {
  721. WaferTask waferATask = WaferTaskManager.Instance.GetWaferTask(WaferHolderInfo.WaferAId);
  722. if (waferATask != null)
  723. {
  724. waferATask.RemoveSrdScheduler();
  725. }
  726. WaferTask waferBTask = WaferTaskManager.Instance.GetWaferTask(WaferHolderInfo.WaferBId);
  727. if (waferBTask != null)
  728. {
  729. waferBTask.RemoveSrdScheduler();
  730. }
  731. }
  732. #endregion
  733. /// <summary>
  734. /// 自动更新LoaderTransporter的工序
  735. /// </summary>
  736. private void AutoChangeLoaderTransporterScheduler()
  737. {
  738. if(_currentSequenceIndex>=_schedulerSequences.Count)
  739. {
  740. return;
  741. }
  742. if(_currentSequenceIndex+2>=_schedulerSequences.Count)
  743. {
  744. return;
  745. }
  746. SchedulerSequence schedulerSequence = _schedulerSequences[_currentSequenceIndex];
  747. if (schedulerSequence == null)
  748. {
  749. return;
  750. }
  751. if(schedulerSequence.ModuleName==ModuleName.Transporter2)
  752. {
  753. if (schedulerSequence.Parameters == null || !(schedulerSequence.Parameters is TransporterAction))
  754. {
  755. return;
  756. }
  757. TransporterAction action = (TransporterAction)schedulerSequence.Parameters;
  758. if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)
  759. {
  760. return;
  761. }
  762. WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)action.Parameter;
  763. if(waferHolderMoveItem.DestModuleType!=ModuleType.Buffer)
  764. {
  765. return;
  766. }
  767. SchedulerSequence nextSchedulerSequence = _schedulerSequences[_currentSequenceIndex + 1];
  768. if(nextSchedulerSequence.ModuleName!=ModuleName.Transporter2)
  769. {
  770. return;
  771. }
  772. if(nextSchedulerSequence.Parameters==null||!(nextSchedulerSequence.Parameters is TransporterAction))
  773. {
  774. return;
  775. }
  776. TransporterAction nextAction = nextSchedulerSequence.Parameters as TransporterAction;
  777. if (nextAction.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)
  778. {
  779. return;
  780. }
  781. WaferHolderMoveItem nextWaferHolderMoveItem = (WaferHolderMoveItem)nextAction.Parameter;
  782. if(nextWaferHolderMoveItem.DestModule==ModuleName.Unknown)
  783. {
  784. if (ProcessJobInfo != null && ProcessJobInfo.SequenceRecipe != null)
  785. {
  786. //后面不存在资源,搬运至Buffer中,而不是进后面cell
  787. if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(ProcessJobInfo.SequenceRecipe, false))
  788. {
  789. return;
  790. }
  791. }
  792. if (CheckBufferHasUnProcessedWaferHolder())
  793. {
  794. return;
  795. }
  796. //若Buffer后面的cell存在资源,则直接搬运至Cell中
  797. ModuleName avaibleModuleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(nextWaferHolderMoveItem.DestModuleType,_sequenceType);
  798. if(avaibleModuleName==ModuleName.Unknown)
  799. {
  800. return;
  801. }
  802. else
  803. {
  804. schedulerSequence.State = RState.End;
  805. _currentSequenceIndex++;
  806. nextWaferHolderMoveItem.DestModule = avaibleModuleName;
  807. nextWaferHolderMoveItem.SourceModule = ModuleName.Loader1;
  808. nextWaferHolderMoveItem.SourceModuleType = ModuleType.Loader;
  809. UpdateNextSequenceModule(_currentSequenceIndex + 1,avaibleModuleName);
  810. }
  811. }
  812. //下一步是QDR
  813. else if (nextWaferHolderMoveItem.DestModuleType == ModuleType.Rinse && nextWaferHolderMoveItem.DestModule != ModuleName.Unknown)
  814. {
  815. RinseEntity rinseEntity = Singleton<RouteManager>.Instance.GetModule<RinseEntity>(nextWaferHolderMoveItem.DestModule.ToString());
  816. if (rinseEntity != null && rinseEntity.IsAuto && rinseEntity.IsIdle && rinseEntity.WaferHolderInfo == null)
  817. {
  818. schedulerSequence.State = RState.End;
  819. _currentSequenceIndex++;
  820. nextWaferHolderMoveItem.SourceModule = ModuleName.Loader1;
  821. nextWaferHolderMoveItem.SourceModuleType = ModuleType.Loader;
  822. UpdateNextSequenceModule(_currentSequenceIndex + 1, nextWaferHolderMoveItem.DestModule);
  823. }
  824. }
  825. else if(nextWaferHolderMoveItem.DestModule==ModuleName.Loader1)
  826. {
  827. LoaderEntity loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());
  828. if(loaderEntity==null)
  829. {
  830. return;
  831. }
  832. if(loaderEntity.WaferHolderInfo!=null)
  833. {
  834. return;
  835. }
  836. if(loaderEntity.IsBusy)
  837. {
  838. return;
  839. }
  840. schedulerSequence.State = RState.End;
  841. _currentSequenceIndex++;
  842. nextWaferHolderMoveItem.SourceModule = waferHolderMoveItem.SourceModule;
  843. nextWaferHolderMoveItem.SourceModuleType = waferHolderMoveItem.SourceModuleType;
  844. }
  845. }
  846. }
  847. /// <summary>
  848. /// 检验Buffer中是否存在未处理的WaferHolder
  849. /// </summary>
  850. /// <returns></returns>
  851. private bool CheckBufferHasUnProcessedWaferHolder()
  852. {
  853. List<string> bufferModules = BufferItemManager.Instance.InstalledModules;
  854. foreach (string module in bufferModules)
  855. {
  856. WaferHolderInfo item = WaferHolderManager.Instance.GetWaferHolder(module);
  857. if (item == null)
  858. {
  859. continue;
  860. }
  861. if (string.IsNullOrEmpty(item.WaferAId))
  862. {
  863. continue;
  864. }
  865. if (string.IsNullOrEmpty(item.WaferBId))
  866. {
  867. continue;
  868. }
  869. WaferInfo waferA=WaferManager.Instance.GetWaferByWaferId(item.WaferAId);
  870. if (waferA == null)
  871. {
  872. continue;
  873. }
  874. if (waferA.ProcessState == EnumWaferProcessStatus.Idle&&waferA.WaferType==WaferType.Production)
  875. {
  876. return true;
  877. }
  878. WaferInfo waferB = WaferManager.Instance.GetWaferByWaferId(item.WaferBId);
  879. if(waferB == null)
  880. {
  881. continue;
  882. }
  883. if (waferB.ProcessState == EnumWaferProcessStatus.Idle && waferB.WaferType == WaferType.Production)
  884. {
  885. return true;
  886. }
  887. }
  888. return false;
  889. }
  890. /// <summary>
  891. /// 更新下一工序的调度模块
  892. /// </summary>
  893. /// <param name="sequenceIndex"></param>
  894. /// <param name="moduleName"></param>
  895. private void UpdateNextSequenceModule(int sequenceIndex,ModuleName moduleName)
  896. {
  897. if(sequenceIndex<_schedulerSequences.Count)
  898. {
  899. SchedulerSequence schedulerSequence = _schedulerSequences[sequenceIndex];
  900. if(schedulerSequence!=null&&schedulerSequence.SchedulerModule==null)
  901. {
  902. schedulerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(moduleName);
  903. schedulerSequence.ModuleName = moduleName;
  904. }
  905. }
  906. }
  907. /// <summary>
  908. /// 更新WaferHolder工序完成Wafer状态
  909. /// </summary>
  910. private void UpdateWaferHolderProcessComplete()
  911. {
  912. if (WaferHolderInfo.Status != WaferHolderStatus.Completed)
  913. {
  914. UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.Completed);
  915. WaferHolderInfo.Status = WaferHolderStatus.Completed;
  916. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Status changed to {WaferHolderInfo.Status}");
  917. }
  918. MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);
  919. }
  920. /// <summary>
  921. /// 更新WaferHolder工序正在加工
  922. /// </summary>
  923. private void UpdateWaferHolderProcessingStatus()
  924. {
  925. if (WaferHolderInfo.Status == WaferHolderStatus.Normal)
  926. {
  927. UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.InProcess);
  928. WaferHolderInfo.Status = WaferHolderStatus.Processing;
  929. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Status changed to {WaferHolderInfo.Status}");
  930. MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);
  931. }
  932. }
  933. /// <summary>
  934. /// 更新WaferHolder工序错误状态
  935. /// </summary>
  936. /// <param name="sequence"></param>
  937. private void UpdateWaferHolderErrorStatus()
  938. {
  939. UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.Failed);
  940. WaferHolderInfo.Status = WaferHolderStatus.Failed;
  941. MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);
  942. }
  943. /// <summary>
  944. /// 更新WaferHolder工序MisProcessed状态
  945. /// </summary>
  946. /// <param name="sequence"></param>
  947. private void UpdateWaferHolderMisProcessedStatus()
  948. {
  949. UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.MisProcessed);
  950. WaferHolderInfo.Status = WaferHolderStatus.MisProcessed;
  951. MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);
  952. }
  953. /// <summary>
  954. /// 更新WaferHolder处理状态
  955. /// </summary>
  956. /// <param name="sequence"></param>
  957. /// <param name="processStatus"></param>
  958. private void UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus processStatus)
  959. {
  960. if (Enum.TryParse(WaferHolderInfo.CurrentLocation, out ModuleName moduleName))
  961. {
  962. if (!string.IsNullOrEmpty(WaferHolderInfo.WaferAId))
  963. {
  964. WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferAId);
  965. if (waferInfo != null && waferInfo.WaferType == WaferType.Production)
  966. {
  967. WaferManager.Instance.UpdateWaferProcessStatus(moduleName, 0, processStatus);
  968. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{waferInfo.WaferID} status changed to {processStatus}");
  969. }
  970. }
  971. if (!string.IsNullOrEmpty(WaferHolderInfo.WaferBId))
  972. {
  973. WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferBId);
  974. if (waferInfo != null && waferInfo.WaferType == WaferType.Production)
  975. {
  976. WaferManager.Instance.UpdateWaferProcessStatus(moduleName, 1, processStatus);
  977. LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{waferInfo.WaferID} status changed to {processStatus}");
  978. }
  979. }
  980. }
  981. }
  982. /// <summary>
  983. /// 检验前置条件
  984. /// </summary>
  985. /// <returns></returns>
  986. private bool CheckStartCondition()
  987. {
  988. LoaderEntity loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());
  989. if (loaderEntity.WaferHolderInfo != null)
  990. {
  991. return false;
  992. }
  993. //if (ProcessJobInfo != null)
  994. //{
  995. // if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(ProcessJobInfo.SequenceRecipe, false))
  996. // {
  997. // _currentSequenceIndex = _schedulerSequences.Count;
  998. // LOG.WriteLog(eEvent.WARN_SCHEDULER, "System", $"WaferHolder {WaferHolderInfo.Id} start scheduler meet no avaible cell");
  999. // return false;
  1000. // }
  1001. //}
  1002. return true;
  1003. }
  1004. /// <summary>
  1005. /// 释放资源
  1006. /// </summary>
  1007. public void Dispose()
  1008. {
  1009. _schedulerSequences.Clear();
  1010. }
  1011. /// <summary>
  1012. /// 暂停
  1013. /// </summary>
  1014. public void Pause()
  1015. {
  1016. _pausedIndex = _currentSequenceIndex;
  1017. }
  1018. /// <summary>
  1019. /// 恢复
  1020. /// </summary>
  1021. public void Resume()
  1022. {
  1023. _pausedIndex = -1;
  1024. }
  1025. /// <summary>
  1026. /// 获取当前调度阶段
  1027. /// </summary>
  1028. /// <returns></returns>
  1029. public SchedulerSequence GetCurrentSchedulerSequence()
  1030. {
  1031. return GetSchedulerSequenceByIndex(_currentSequenceIndex);
  1032. }
  1033. /// <summary>
  1034. /// 获取前一个调度阶段
  1035. /// </summary>
  1036. /// <returns></returns>
  1037. public SchedulerSequence GetPreSchedulerSequence()
  1038. {
  1039. return GetSchedulerSequenceByIndex(_currentSequenceIndex-1);
  1040. }
  1041. /// <summary>
  1042. /// 根据索引获取调度阶段对象
  1043. /// </summary>
  1044. /// <param name="index"></param>
  1045. /// <returns></returns>
  1046. private SchedulerSequence GetSchedulerSequenceByIndex(int index)
  1047. {
  1048. if (index == -1 || index >= _schedulerSequences.Count)
  1049. {
  1050. return null;
  1051. }
  1052. return _schedulerSequences[index];
  1053. }
  1054. /// <summary>
  1055. /// 是否调度完成Loader调度
  1056. /// </summary>
  1057. /// <returns></returns>
  1058. public bool IsNotPassLoader()
  1059. {
  1060. return _currentSequenceIndex <= 1;
  1061. }
  1062. }
  1063. }