Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple state machine example in C#?

Update:

Again thanks for the examples, they have been very helpful and with the following, I don't mean to take anything away from them.

Aren't the currently given examples, as far as I understand them & state-machines, only half of what we usually understand by a state-machine?
In the sense that the examples do change state but that's only represented by changing the value of a variable (and allowing different value- changes in different states), while usually, a state machine should also change its behavior, and behavior not (only) in the sense of allowing different value changes for a variable depending on the state, but in the sense of allowing different methods to be executed for different states.

Or do I have a misconception of state machines and their common use?


Original question:

I found this discussion about state machines & iterator blocks in c# and tools to create state machines and whatnot for C#, so I found a lot of abstract stuff but as a noob, all of this is a little confusing.

So it would be great if someone could provide a C# source code-example that realizes a simple state machine with perhaps 3,4 states, just to get the gist of it.

like image 318
Jennifer Owens Avatar asked May 07 '11 20:05

Jennifer Owens


People also ask

What is an example of a state machine?

There are many more examples of finite state machines we could use: a vending machine. a subway entrance turnstile. a heating system.

What is a state machine in C?

A state machine is any object that behaves different based on its history and current inputs. Many embedded systems consist of a collection of state machines at various levels of the electronics or software.

What is state machine model discuss with an example?

State Machine Diagrams. A state machine diagram models the behaviour of a single object, specifying the sequence of events that an object goes through during its lifetime in response to events. As an example, the following state machine diagram shows the states that a door goes through during its lifetime.

Is a switch statement a state machine?

The big switch statement. Various approaches are possible for implementing an automatic state machine in software. The most common is using a switch statement. Developers often implement state-of-the-art switches with switch instructions, even if they are not aware that they are state machines.


2 Answers

Let's start with this simple state diagram:

simple state machine diagram

We have:

  • 4 states (Inactive, Active, Paused, and Exited)
  • 5 types of state transitions (Begin Command, End Command, Pause Command, Resume Command, Exit Command).

You can convert this to C# in a handful of ways, such as performing a switch statement on the current state and command, or looking up transitions in a transition table. For this simple state machine, I prefer a transition table, which is very easy to represent using a Dictionary:

using System; using System.Collections.Generic;  namespace Juliet {     public enum ProcessState     {         Inactive,         Active,         Paused,         Terminated     }      public enum Command     {         Begin,         End,         Pause,         Resume,         Exit     }      public class Process     {         class StateTransition         {             readonly ProcessState CurrentState;             readonly Command Command;              public StateTransition(ProcessState currentState, Command command)             {                 CurrentState = currentState;                 Command = command;             }              public override int GetHashCode()             {                 return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();             }              public override bool Equals(object obj)             {                 StateTransition other = obj as StateTransition;                 return other != null && this.CurrentState == other.CurrentState && this.Command == other.Command;             }         }          Dictionary<StateTransition, ProcessState> transitions;         public ProcessState CurrentState { get; private set; }          public Process()         {             CurrentState = ProcessState.Inactive;             transitions = new Dictionary<StateTransition, ProcessState>             {                 { new StateTransition(ProcessState.Inactive, Command.Exit), ProcessState.Terminated },                 { new StateTransition(ProcessState.Inactive, Command.Begin), ProcessState.Active },                 { new StateTransition(ProcessState.Active, Command.End), ProcessState.Inactive },                 { new StateTransition(ProcessState.Active, Command.Pause), ProcessState.Paused },                 { new StateTransition(ProcessState.Paused, Command.End), ProcessState.Inactive },                 { new StateTransition(ProcessState.Paused, Command.Resume), ProcessState.Active }             };         }          public ProcessState GetNext(Command command)         {             StateTransition transition = new StateTransition(CurrentState, command);             ProcessState nextState;             if (!transitions.TryGetValue(transition, out nextState))                 throw new Exception("Invalid transition: " + CurrentState + " -> " + command);             return nextState;         }          public ProcessState MoveNext(Command command)         {             CurrentState = GetNext(command);             return CurrentState;         }     }       public class Program     {         static void Main(string[] args)         {             Process p = new Process();             Console.WriteLine("Current State = " + p.CurrentState);             Console.WriteLine("Command.Begin: Current State = " + p.MoveNext(Command.Begin));             Console.WriteLine("Command.Pause: Current State = " + p.MoveNext(Command.Pause));             Console.WriteLine("Command.End: Current State = " + p.MoveNext(Command.End));             Console.WriteLine("Command.Exit: Current State = " + p.MoveNext(Command.Exit));             Console.ReadLine();         }     } } 

As a matter of personal preference, I like to design my state machines with a GetNext function to return the next state deterministically, and a MoveNext function to mutate the state machine.

like image 127
Juliet Avatar answered Oct 16 '22 03:10

Juliet


You might want to use one of the existing open source Finite State Machines. E.g. bbv.Common.StateMachine found at http://code.google.com/p/bbvcommon/wiki/StateMachine. It has a very intuitive fluent syntax and a lot of features such as, enter/exit actions, transition actions, guards, hierarchical, passive implementation (executed on the thread of the caller) and active implementation (own thread on which the fsm runs, events are added to a queue).

Taking Juliets example the definition for the state machine gets very easy:

var fsm = new PassiveStateMachine<ProcessState, Command>(); fsm.In(ProcessState.Inactive)    .On(Command.Exit).Goto(ProcessState.Terminated).Execute(SomeTransitionAction)    .On(Command.Begin).Goto(ProcessState.Active); fsm.In(ProcessState.Active)    .ExecuteOnEntry(SomeEntryAction)    .ExecuteOnExit(SomeExitAction)    .On(Command.End).Goto(ProcessState.Inactive)    .On(Command.Pause).Goto(ProcessState.Paused); fsm.In(ProcessState.Paused)    .On(Command.End).Goto(ProcessState.Inactive).OnlyIf(SomeGuard)    .On(Command.Resume).Goto(ProcessState.Active); fsm.Initialize(ProcessState.Inactive); fsm.Start();  fsm.Fire(Command.Begin); 

Update: The project location has moved to: https://github.com/appccelerate/statemachine

like image 42
Remo Gloor Avatar answered Oct 16 '22 02:10

Remo Gloor