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)); }
/// <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); }