protected internal override NSFEventStatus processEvent(NSFEvent nsfEvent)
        {
            // Additional behavior

            // Let regions process event first
            NSFEventStatus eventStatus = NSFEventStatus.NSFEventUnhandled;

            foreach (NSFRegion region in regions)
            {
                NSFEventStatus status = region.processEvent(nsfEvent);

                if (status == NSFEventStatus.NSFEventHandled)
                {
                    eventStatus = NSFEventStatus.NSFEventHandled;
                }
            }

            if (eventStatus == NSFEventStatus.NSFEventHandled)
            {
                return(NSFEventStatus.NSFEventHandled);
            }

            // Base class behavior
            return(base.processEvent(nsfEvent));
        }
Пример #2
0
        /// <summary>
        /// Handles an event.
        /// </summary>
        /// <param name="nsfEvent">The event to handle.</param>
        /// <returns>Status indicating if the event was handled or not.</returns>
        /// <remarks>
        /// This method is for use only by the North State Framework's internal logic.
        /// It processes the event using UML defined behavior, including run to completion.
        /// </remarks>
        public NSFEventStatus handleEvent(NSFEvent nsfEvent)
        {
            lock (stateMachineMutex)
            {
                --QueuedEvents;

                // This should only happen if events are queued without using the queueEvent method
                if (QueuedEvents < 0)
                {
                    QueuedEvents = 0;
                }
            }

            // Handle status changing events
            if ((nsfEvent == startEvent))
            {
                RunStatus = NSFEventHandlerRunStatus.EventHandlerStarted;
            }
            else if (nsfEvent == stopEvent)
            {
                RunStatus = NSFEventHandlerRunStatus.EventHandlerStopped;
            }
            else if (nsfEvent == terminateEvent)
            {
                TerminationStatus = NSFEventHandlerTerminationStatus.EventHandlerTerminated;
                EventThread.removeEventHandler(this);
                return(NSFEventStatus.NSFEventHandled);
            }
            else if (nsfEvent == resetEvent)
            {
                reset();
            }

            // Don't process events if stopped
            if (RunStatus == NSFEventHandlerRunStatus.EventHandlerStopped)
            {
                return(NSFEventStatus.NSFEventUnhandled);
            }

            // If not already active, enter state machine at the root
            if (!active)
            {
                enter(new NSFStateMachineContext(this, this, null, null, startEvent), false);
            }

            // Process the event
            NSFEventStatus eventStatus = NSFEventStatus.NSFEventUnhandled;

            try
            {
                eventStatus = processEvent(nsfEvent);

                if (eventStatus == NSFEventStatus.NSFEventHandled)
                {
                    runToCompletion();
                }

                // Consecutive loop detection looks for too many events without the state machine pausing.
                // If more than the specified number of transitions occur without a pause, the state machine will remove
                // its queued events, call the consecutive loop limit actions, and stop after executing any events queued
                // by the actions.
                if (ConsecutiveLoopDetectionEnabled)
                {
                    ++consecutiveLoopCount;

                    if (consecutiveLoopCount == ConsecutiveLoopLimit)
                    {
                        lock (stateMachineMutex)
                        {
                            EventThread.removeEventsFor(this);
                            QueuedEvents = 0;
                        }

                        ConsecutiveLoopLimitActions.execute(new NSFStateMachineContext(this, null, null, null, nsfEvent));

                        // Stop the state machine so that no more event processing occurs until started again
                        stopStateMachine();

                        // Reset consecutive loop count in case state machine is started again
                        consecutiveLoopCount = 0;

                        NSFTraceLog.PrimaryTraceLog.addTrace(NSFTraceTags.ErrorTag, NSFTraceTags.SourceTag, Name, NSFTraceTags.MessageTag, "ConsecutiveLoopLimit");
                    }
                    else if (QueuedEvents == 0)
                    {
                        // If no events are queued for this state machine, then it has paused, indicating it's not in an infinite loop.
                        consecutiveLoopCount = 0;
                    }
                }
            }
            catch (Exception exception)
            {
                handleException(new Exception(nsfEvent.Name + " event handling exception", exception));
            }

            return(eventStatus);
        }