///// <summary> ///// RunStateMachine is the heart of the engine that runs the finite state machine. It is executed in a ///// separate thread that is started when you <see cref="Start(FiniteState)"/> the state machine. ///// All events that have been queued by <see cref="RaiseEvent(FiniteStateEvent)"/>, are processed here. ///// The method runs in an infinite loop that only exits when <see cref="Stop()"/> is called. ///// When it has processed all of the events in the queue, it will sleep until it is pulsed ///// by either <see cref="RaiseEvent(FiniteStateEvent)"/> or <see cref="Stop()"/> ///// </summary> //public void RunStateMachine() //{ // string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; // if (log.IsDebugEnabled) // log.Debug($"{methodName}: enter"); // // try // { // while (!stopRequested) // { // HandlePendingEvents(); // if (!stopRequested) // { // lock (locker) // { // if (log.IsDebugEnabled) // log.Debug($"{methodName}: Putting to sleep the state machine thread."); // // Monitor.Wait(locker); // Nothing to do, so go to sleep until we are pulsed by RaiseEvent or Stop // // if (log.IsDebugEnabled) // log.Debug($"{methodName}: Just woke up :-)"); // } // } // } // } // catch(Exception e) // { // log.Error($"{e.Message}"); // //OnExceptionAction?.Invoke(e); // } // finally // { // if (log.IsDebugEnabled) // log.Debug($"{methodName}: exit"); // } //} // /// <summary> /// This function is called during the first call to RaiseEvent() in Start() because at that point, /// we are not handling a previous event. From then on, every event handler raises an event. /// </summary> public void HandlePendingEvents() { string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; if (log.IsDebugEnabled) { log.Debug($"{methodName}: enter"); } try { while (PendingEvents.Count > 0) { if (log.IsDebugEnabled) { log.Debug($"{methodName}: PendingEvents.Count={PendingEvents.Count}"); } FiniteStateEvent ev = null; lock (PendingEvents) { ev = PendingEvents.Dequeue(); } if (CurrentState.Transitions.TryGetValue(ev.Name, out FiniteStateTransition transition)) { if (log.IsDebugEnabled) { log.Debug($"{methodName}: transition {CurrentState.Name} -> {ev.Name} ->{transition.ToState.Name}"); } SetCurrentState(transition.ToState); if (log.IsDebugEnabled) { log.Debug($"{methodName}: before invoke, PendingEvents.Count={PendingEvents.Count}"); } CurrentState.OnEnterAction?.Invoke(); if (log.IsDebugEnabled) { log.Debug($"{methodName}: after invoke, PendingEvents.Count={PendingEvents.Count}"); } } else { throw new ArgumentException($"Failed to find a transition for event '{ev.Name}' from state '{CurrentState.Name}'."); } } } finally { if (log.IsDebugEnabled) { log.Debug($"{methodName}: exit"); } } }
protected void Dequeue() { PendingEvents.Dequeue(); }