/// <summary> /// Returns the path to take from here /// </summary> /// <returns></returns> public override SMPathOut Run() { lock (this) { if (HasChildren) { if (NeedsRebuild) { //Rebuild(); } //For dry run if (CompMachine.s_machine.IsDryRun && this.DryRunSkipActions) { // Do no action } else { validMethods.ForEach(c => c.RunAsync()); //Parallel.ForEach(validMethods, method => method.RunAsync()); //// Wait until they all complete WaitHandle.WaitAll(waitHandles); } // Look for any exceptions made by the methods List <Exception> exceptions = new List <Exception>(); foreach (SMMethod method in validMethods) { if (method.methodResults.Exception != null) { exceptions.Add(method.methodResults.Exception); } } //Parallel.ForEach(validMethods, method => //{ // if (method.methodResults.Exception != null) // { // exceptions.Add(method.methodResults.Exception); // } //}); if (exceptions.Count > 0) { // We found at least one exception. Store it with the SMPathOutError SMPathOutError pathError = this[typeof(SMPathOutError)] as SMPathOutError; if (pathError != null) { pathError.Exceptions = exceptions; return(pathError); } } } } // Only one out return(this[typeof(SMPathOut)]); }
/// <summary> /// Returns the path to take from here /// </summary> /// <returns></returns> public override SMPathOut Run() { lock (this) { if (HasChildren || HasTransition) { if (NeedsRebuild) { //Rebuild(); } if (HasMethod) { //For dry run if (CompMachine.s_machine.IsDryRun && this.DryRunSkipActions) { // Do no action } else { //Run All Method //validMethods.ForEach(c => c.RunAsync()); Parallel.ForEach(validMethods, method => method.RunAsync()); //// Wait until they all complete WaitHandle.WaitAll(waitHandles); } } // Look for any exceptions made by the methods List <Exception> exceptions = new List <Exception>(); foreach (SMMethod method in validMethods) { if (method.methodResults.Exception != null) { exceptions.Add(method.methodResults.Exception); } } //Parallel.ForEach(validMethods, method => //{ // if (method.methodResults.Exception != null) // { // exceptions.Add(method.methodResults.Exception); // } //}); if (exceptions.Count > 0) { // We found at least one exception. Store it with the SMPathOutError SMPathOutError pathError = this[typeof(SMPathOutError)] as SMPathOutError; if (pathError != null) { pathError.Exceptions = exceptions; return(pathError); } } if (HasTransition) { bool anyTransPassValidate = false; do { var waitDelay = Task.Delay(10); if (TransTimeOut > 0 && !_stopWatch.IsRunning) { _stopWatch.Restart(); } //Run All Transition validTransitions.ForEach(c => c.RunAsync()); //Parallel.ForEach(validTransitions, transition => transition.RunAsync()); //Wait until all transition run complete WaitHandle.WaitAll(waitHandlesTransitions, 1000); foreach (SMTransition transition in validTransitions) { anyTransPassValidate = anyTransPassValidate || transition.ValidationResult; if (transition.TransitionResults.Exception != null) { exceptions.Add(transition.TransitionResults.Exception); } } //Parallel.ForEach(validTransitions, transition => //{ // anyTransPassValidate = anyTransPassValidate || transition.ValidationResult; // if (transition.TransitionResults.Exception != null) // { // exceptions.Add(transition.TransitionResults.Exception); // } //}); //For dry run if (CompMachine.s_machine.IsDryRun && this.UseDryRunTrans && this.DryRunTransitionTargetID != "") { anyTransPassValidate = true; } if (exceptions.Count > 0) { // We found at least one exception. Store it with the SMPathOutError SMPathOutError pathError = this[typeof(SMPathOutError)] as SMPathOutError; if (pathError != null) { pathError.Exceptions = exceptions; return(pathError); } } //Validate Timeout if (TransTimeOut > 0 && !anyTransPassValidate && (_stopWatch.ElapsedMilliseconds > TransTimeOut)) { SMPathOut stopPath = this[typeof(SMPathOutStop)]; //Display message in case no path error connected if (stopPath == null || !stopPath.HasTargetID || !FlowTimeoutToStopPath) { string caption = TimeOutCaption; if (caption == "") { caption = "Transition TimeOut"; } string msg = TimeOutMessage; if (msg == "") { msg = String.Format("Transition TimeOut [{0}] on state [{1}]", this.PathText, this.StateMachine); } _stopWatch.Stop(); _timeoutHandle.Reset(); DisplayAsynchMsg(msg, caption); _timeoutHandle.WaitOne(); _timeoutHandle.Reset(); } else { _stopWatch.Stop(); _timeoutHandle.Reset(); return(this[typeof(SMPathOutStop)]); } } waitDelay.Wait(); }while (!anyTransPassValidate && LoopTransitions && !StateMachine.ReceivedStop); } _stopWatch.Stop(); _timeoutHandle.Reset(); } if (!StateMachine.ReceivedStop) { //For dry run if (CompMachine.s_machine.IsDryRun && this.UseDryRunTrans && this.DryRunTransitionTargetID != "") { _dryRunPath.TargetID = this.DryRunTransitionTargetID; _dryRunPath.Initialize(this, true); return(_dryRunPath); } //Check First OK Transition Path Out foreach (SMTransition transition in validTransitions) { if (transition.ValidationResult && transition.TransitionPath.TargetID != "") { return(transition.TransitionPath); } } } } // Only one out return(this[typeof(SMPathOut)]); }
public override SMPathOut Run() { lock (this) { if (HasChildren) { do { var waitDelay = Task.Delay(10); if (TransTimeOut > 0 && !_stopWatch.IsRunning) { _stopWatch.Restart(); } try { if (this.HasChildren) { ValidationResult = (this.ChildArray[0] as SMSubCondBase).Validate(); } //For dry run if (CompMachine.s_machine.IsDryRun && this.UseDryRunTrans && this.DryRunTransitionTargetID != "") { ValidationResult = true; _dryRunPath.TargetID = this.DryRunTransitionTargetID; _dryRunPath.Initialize(this, true); return(_dryRunPath); } if (ValidationResult && _transitionPath.TargetID != "") { return(_transitionPath); } } catch (Exception ex) { _stopWatch.Stop(); _timeoutHandle.Reset(); // We found at least one exception. Store it with the SMPathOutError SMPathOutError pathError = this[typeof(SMPathOutError)] as SMPathOutError; if (pathError != null) { pathError.Exceptions.Add(ex); return(pathError); } } //Validate Timeout if (TransTimeOut > 0 && !ValidationResult && (_stopWatch.ElapsedMilliseconds > TransTimeOut)) { SMPathOut stopPath = this[typeof(SMPathOutStop)]; //Display message in case no path error connected if (stopPath == null || !stopPath.HasTargetID || !FlowTimeoutToStopPath) { string caption = TimeOutCaption; if (caption == "") { caption = "Transition TimeOut"; } string msg = TimeOutMessage; if (msg == "") { msg = String.Format("Transition TimeOut [{0}] on state [{1}]", this.PathText, this.StateMachine); } _stopWatch.Stop(); _timeoutHandle.Reset(); DisplayAsynchMsg(msg, caption); _timeoutHandle.WaitOne(); _timeoutHandle.Reset(); } else { _stopWatch.Stop(); _timeoutHandle.Reset(); return(this[typeof(SMPathOutStop)]); } } waitDelay.Wait(); } while (!ValidationResult && LoopTransition && !StateMachine.ReceivedStop); _stopWatch.Stop(); _timeoutHandle.Reset(); } //Always true if no any condition in child array else { ValidationResult = true; if (ValidationResult && _transitionPath.TargetID != "") { return(_transitionPath); } } } // Only one out return(this[typeof(SMPathOut)]); }
/// <summary> /// Run method for the main state machine thread /// </summary> /// <returns></returns> public override SMPathOut Run() { //SMStateMachine stateMachine = StateMachine; try { //_timeoutHandle.Reset(); //ManualResetEvent waitHandle = stateMachine.WaitHandle; //ManualResetEvent decisionWaitHandle = stateMachine.DecisionWaitHandle; //List<SMDecision> decisionLoopList = stateMachine.DecisionLoopList; //SMPathOut pathOut = null; //SMFlowBase flowItemForPathOut = null; //_decisionTimeout = -1; //ExitFlowItem(); //FindStart(); //// Hightlight start //EnterFlowItem(); PreRun(); while (true) { Thread.Sleep(0); // If Reset will block thread (Pause) until Step or Run (Set) if (stateMachine.Mode == SMStateMachine.eMode.Pause) { waitHandle.Reset(); // Wait until(Pause) until Step or Run (Set) EnterFlowItem(); waitHandle.WaitOne(); ExitFlowItem(); } if (_currentFlowItem is SMDecision) { SMDecision decisionItem = _currentFlowItem as SMDecision; if (decisionLoopList.Contains(decisionItem)) { // We have closed the loop of nothing but decision items EnterFlowItem(); //stateMachine.EnterPathItem(flowItemForPathOut, flowItemForPathOut.OutgoingPath); // Modify by Kasem 12-Feb-2018 if (decisionItem.WaitTimeoutMS <= 0) { decisionWaitHandle.WaitOne(_decisionTimeout); } else { Boolean signal = false; signal = decisionWaitHandle.WaitOne(decisionItem.WaitTimeoutMS); //Trigger Timeout if (!signal) { _timeoutHandle.Set(); } } //-------------------------------- _decisionTimeout = -1; //stateMachine.ExitPathItem(flowItemForPathOut, flowItemForPathOut.OutgoingPath); ExitFlowItem(); stateMachine.ClearDecisionList(); } else { if (decisionLoopList.Count == 0) { // First one. Reset early in case something changes quickly decisionWaitHandle.Reset(); } decisionItem.AddNotifier(StateMachine.OnDecisionChanged); stateMachine.AddToDecisionList(decisionItem, flowItemForPathOut, pathOut); } } else { stateMachine.ClearDecisionList(); } // // Run this item // //Dump Process Usage Timing if (CompMachine.s_machine.ProcessUsageTrigger) { if (!(_currentFlowItem is SMFlowContainer)) { StateMachine.AddTimingElement(">Run: " + _currentFlowItem.Text); } else { StateMachine.AddTimingElement(">Enter: " + _currentFlowItem.Text); } } EnterFlowItem(); pathOut = _currentFlowItem.Run(); ExitFlowItem(); //Dump Process Usage Timing if (CompMachine.s_machine.ProcessUsageTrigger) { if (!(_currentFlowItem is SMFlowContainer)) { StateMachine.AddTimingElement("<Run: " + _currentFlowItem.Text); } else { StateMachine.AddTimingElement("<Exit: " + _currentFlowItem.Text); } } //Add by Kasem 12-Feb-2018 if (_currentFlowItem is SMDecision) { //Determine Start to Capture Timeout SMDecision decisionItem = _currentFlowItem as SMDecision; //No Partout Meaning Waiting Condition if (pathOut != null && !pathOut.HasTargetID && decisionItem.WaitTimeoutMS > 0) { //Start Stop watch if Nested Condition if (!_stopWatch.IsRunning && _currentFlowItem.HasChildren) { _stopWatch.Restart(); } else if (_stopWatch.IsRunning && !_currentFlowItem.HasChildren) { _stopWatch.Stop(); } else { if ((_currentFlowItem.HasChildren) && (_stopWatch.ElapsedMilliseconds > decisionItem.WaitTimeoutMS) || (!_currentFlowItem.HasChildren) && _timeoutHandle.WaitOne(0)) { //Check Stop Path and Flow to Timeout Flag SMPathOut stopPath = _currentFlowItem[typeof(SMPathOutStop)]; //Popup in case no path for Timeout if (!decisionItem.FlowTimeoutToStopPath || stopPath == null || !stopPath.HasTargetID) { U.LogWarning("Decision Wait Time Out [{0}] on state [{1}]", decisionItem.PathText, this.StateMachine); string msg = String.Format("Decision Wait Time Out [{0}] on state [{1}]", decisionItem.PathText, this.StateMachine); _stopWatch.Stop(); _timeoutHandle.Reset(); DisplayAsynchMsg(msg); _timeoutHandle.WaitOne(); _timeoutHandle.Reset(); } //Case Timeout path available else { _stopWatch.Stop(); _timeoutHandle.Reset(); pathOut = stopPath; } } } } //Force pathout to null incase of pathout is stop path but we use FlowTimeoutToStopPath option else if (pathOut is SMPathOutStop && decisionItem.FlowTimeoutToStopPath) { pathOut = null; _stopWatch.Stop(); } //Stop capture time in case decision meet wait condition else { _stopWatch.Stop(); } } //Modify by Kasem 13-Feb-2018 if (stateMachine.ReceivedStop) { if (!(_currentFlowItem is SMDecision) && !(_currentFlowItem is SMTransition) && !(_currentFlowItem is SMActTransFlow)) { stateMachine.ReceivedStop = false; // Redirect the path to the PathOutStop pathOut = _currentFlowItem[typeof(SMPathOutStop)]; } else { stateMachine.ReceivedStop = false; _stopWatch.Stop(); if (_currentFlowItem is SMDecision) { if (!(_currentFlowItem as SMDecision).FlowTimeoutToStopPath) { pathOut = _currentFlowItem[typeof(SMPathOutStop)]; } else { pathOut = null; } } else if (_currentFlowItem is SMTransition) { if (!(_currentFlowItem as SMTransition).FlowTimeoutToStopPath) { pathOut = _currentFlowItem[typeof(SMPathOutStop)]; } else { pathOut = null; } } else if (_currentFlowItem is SMActTransFlow) { if (!(_currentFlowItem as SMActTransFlow).FlowTimeoutToStopPath) { pathOut = _currentFlowItem[typeof(SMPathOutStop)]; } else { pathOut = null; } } } } //-------------------------------- if (pathOut == null) { // Will stop the whole State Machine return(null); } SMPathOutError pathOutError = pathOut as SMPathOutError; if (pathOutError != null) { pathOutError.ProcessErrors(); } if (pathOut.HasTargetID) { flowItemForPathOut = _currentFlowItem; // We are on the target path. _currentFlowItem = GetFlowTarget(pathOut); _currentFlowItem.IncomingPath = pathOut; } else if ((_currentFlowItem is SMDecision) && !(pathOut is SMPathOutStop) && !(pathOut is SMPathOutError)) { // Keep same current flow item. Let it loop to itself } else { // No target to go to // Will stop the whole State Machine if ((pathOut is SMPathOutStop) || (pathOut is SMPathOutError)) { if (!FindStop()) { FindStart(); } EnterFlowItem(); } _currentFlowItem.IncomingPath = null; return(null); } if (_currentFlowItem == null) { throw new Exception(string.Format("Could not locate Flowitem from ID '{0}' in StateMachine '{1}'. State Machine has paused.", pathOut.TargetID, Text)); } if (_currentFlowItem is SMExit) { EnterFlowItem(); if (this is SMDecision) { foreach (SMPathOut path in PathArray) { if (_currentFlowItem is SMReturnNo) { if (path is SMPathOutBool && !(path as SMPathOutBool).True) { return(path); } } else if (_currentFlowItem is SMReturnYes) { if (path is SMPathOutBool && (path as SMPathOutBool).True) { return(path); } } else if (_currentFlowItem is SMReturnStop) { if (path is SMPathOutStop) { return(path); } } } } if (this is SMSubroutine && _currentFlowItem is SMReturnStop) { return(this[typeof(SMPathOutStop)]); } return(this[typeof(SMPathOut)]); } }//End While True; } finally { stateMachine.ClearDecisionList(); _isAlreadyPreRun = false; System.Threading.Tasks.Task.Run(() => PreRun()); } }