|

Motivation
In automation and other multi-threading programming disciplines, the Finite State Machine (FSM) is an important model for designing dynamic behavior. The FSM is an object, which is always in one state of a defined set of states. It is able to receive events from a set of events, depending on the actual state. Upon receiving a given event, the FSM executes a specific transition. I created a framework of classes which simplifies the implementation of FSMs in .NET applications.
Background
A common approach to implement an FSM is a cross-table with the states on one axis and the events on the other axis. In the crossfields, you define the actions (if there are any). Unfortunately, this approach is not object-oriented. Another approach comes from “the Gang of Four” (Gamma, etc.) with their design pattern “States”. This is an object-oriented approach with a class for each event and each state. Even if this is a very flexible solution, it is somewhat “talkative”: you need a lot of classes and relations between these classes for a single FSM.
The approach described here is also object oriented, but requires less code than the "States"-pattern. You write handler methods for your Fsm class. But you need not bind them to events and states. This is done automatically in the startup of your program. In the startup phase, the Fsm gathers all necessary information from your source by the reflection capabilities of .NET. You just have to follow some naming and signature rules, that's it! Or, if you want to have more control over the binding, you can tag classes, members and methods with some attributes. The price you have to pay is some “magic” behavior behind the code and some loss of transparency.
Features
- Supports multithreading
- Supports multiple FSMs on one thread
- Supports timer events
- Allows definition of transition handlers and / or event handlers
- Supports state entry and exit handlers
- Allows definition default transition and event handlers
- Minimal effort to write an FSM, you write simply less code
- Flexible through optional usage of attributes
- Allows one-to-one translation from UML state diagrams
Implementing an FSM, Step by Step
- Derive a class from the RTLib base class
Fsm. Add a state enumeration type and a state member state. Override the GetCurrentState method. Initialize state with the initial state: public class MyFsm : RTLib.Fsm
{
public enum MyState
{
MyState1,
MyState2,
MyState3
};
public MyFsm ()
{
state = MyState.MyState1;
}
private MyState state;
override protected int GetCurrentState()
{
return (int)state;
}
}
Note: The only reason for GetCurrentState() is that the Fsm class gets to know the current state. I did not find a way to create it automatically by reflection.
- Define your event classes. Every event type is a class derived from the base class
FsmEvent. There exists special event base classes for timer events and synchronizable events. Even it is possible to define them public, they are usually private to your Fsm as nested classes. Examples: private class MyEvent : RTLib.FsmEvent
{
public MyEvent()
{
}
}
private class MyEventWithParam : RTLib.FsmEvent
{
public MyEventWithParam(Param1Type param1)
{
this.param1 = param1
}
public Param1Type Param1
{
get { return param1;}
}
private Param1Type param1;
}
private class MyTimerEvent : FsmTimerEvent
{
public MyEventA()
: base( new TimeSpan(0,0,6) )
{
}
}
private class MyAbsoluteTimerEvent : FsmTimerEvent
{
public MyEventA(): base( new DateTime(DateTime.Now.Year,
DateTime.Now.Month, DateTime.Now.Day,
12, 0, 0) )
{
}
}
- Define your transition-, event- and state handlers.
| Transition Handler |
A method, which is called upon receiving a specific event in a certain state. Either you can use the naming convention State_Xxxxx(MyEvent) or you can define a method attribute [FsmTransitionHandler("State")]. If you define a transition handler with an event parameter of the base event class FsmEvent, it is a default transition handler for this state. This can be used to implement default handling for unexpected events. |
| Event Handler |
A method, which is called upon receiving a specific event in an FSM without states or with no transition handler for this event and the current state. Either you can use the naming convention Xxxxx(MyEvent) or you can define a method attribute [FsmEventHandler]. |
| State Handler |
A method, which is called upon entering or on exit of a certain state. Either you can use the naming convention State_EntryState(), respective State_ExitState() or you can define a method attribute [FsmStateHandler("State", EStateHandlerType.Entry )], respective [FsmStateHandler("State", EStateHandlerType.Exit )]. |
Important note: Attributes can be used only if your FSM class has the following attribute: [FsmCoding(ECodingType.WithAttributes)]. If you want to suppress resolution of the naming convention in an FSM without attribute usage, you can use the method attribute [FsmNoHandler] for any kind of handler methods.
Examples:
private void MyState1_OnMyEventWithParam( MyEventWithParam ev )
{
Trace.Write(DateTime.Now+" "+GetType().Name+": ");
Trace.Write("MyState1_OnMyEventWithParam, Param = ");
Trace.WriteLine(ev.Param1);
state = MyState.MyState2;
}
[FsmTransitionHandler("MyState1")]
private void TransitionHandlerWithAttribute( MyEvent ev )
{
Trace.Write(DateTime.Now+" "+GetType().Name+": ");
Trace.Write("TransitionhandlerWithAttribute");
state = MyState.MyState2;
}
private void MyState1_EntryState( FsmEvent ev, State oldState)
{
Trace.Write(DateTime.Now+" "+GetType().Name+": ");
Trace.WriteLine("MyState1_EntryState, oldState = "+oldState.ToString() );
}
private void OnMyEventWithParam( MyEvent ev )
{
Trace.Write(DateTime.Now+" "+GetType().Name+": ");
Trace.WriteLine("OnMyEvent");
}
- Create an
FsmProcessor object and push the FSM to it. If you want to synchronize to completion of the FSM, add also a Wait() call: FsmProcessor processor = new FsmProcessor("MyProc");
MyFsm myFsm = new MyFsm();
processor.PushFsm(myFsm);
myFsm.Wait();
Note: With Wait(), it is also possible to synchronize to the processing of a posted event if it is derived from SyncEvent. Fsm and EventBase have a constructor with a synchronized parameter.
- There are several ways to terminate the FSM:
| FSM Internally |
In any handler, call the base method TerminateFsm() |
| FSM Externally and FSM Internally |
Call Terminate() on Fsm or TerminateFsm(Fsm) on FsmProcessor |
| FSM Externally |
Call TerminateAllFsm(delay) on FsmProcessor |
Classes in RTLib

Fsm |
Base class for all FSMs. Implements all the "magics" with reflection. Has some overridables for entry and exit-code. Synchronization to completion can be enabled. |
FsmProcessor |
Encapsulates a thread for the usage with FSMs. It maintains an event queue, which is processed in the context of the thread. FSMs and events can be posted to this queue. |
FsmEvent |
Base class for all events used with FSMs. To send an event to a FSM it should be posted to the processor the FSM is running on. There exists a constructor which allows to create a synchronized event like with FsmSyncEvent. |
FsmSyncEvent |
Base class for events you want to synchronize to its completion. Actually, FsmEvent supports a sync event which is enabled in the constructor of FsmSyncEvent. |
FsmTimerEvent |
A specialized FsmEvent for timer usage. It can be used for single shot, n repeats or endless repeats. You can define relative timers (with TimeSpan parameter) or absolute timers (with DateTime parameter). Fsm is the base class of all FSMs. Is is also derived from FsmEventBase. |
FSM Entry and Exit Code
When an FSM is posted, the thread associated with the FSM processor calls first the override method OnFsmEntry(). When an FSM terminates the thread associated with the FSM processor calls the override method OnFsmExit() just before the FSM object is deleted. By overriding these methods, the user has a chance to execute some initialization and clean-up code in the context of the FSM processor thread the FSM is executing on.
Event Processing
For performance reasons, all time consuming reflection code is done at start-up time. At runtime, just a few look-ups are necessary to find and call the right handler method. An FSM can have a state variable or not. This has influence to the event handling. With states, the FSM handles the events in the following order:
With states:
- Try to dispatch the event to a transition handler.
- If not existing, try to dispatch the event to a default transition handler.
- If not existing, try to dispatch the event to a event handler.
- If not existing, call the default event handler.
- If not overridden, output an error trace.
Without states:
- If not existing, try to dispatch the event to a event handler.
- If not existing, call the default event handler.
- If not overridden, output an error trace.
Attributes and Naming Convention
| Attribute |
Naming Convention |
Description |
FsmCoding |
Default |
Used for an Fsm class to force using attributes (ECodingType.WithAttributes) or naming convention and signature match (ECodingType.Automatic) is used. Default is ECodingType.Automatic. There is one attribute used with automatic: FsmNoHandler |
FsmNoHandler |
[FsmNoHandler] |
Discriminator in ECodingType.Automatic mode. Allows to exclude a method from FSM processing even if it follows the naming convention. |
FsmState |
state |
Defines the state variable in the FSM. The variable must be of type enum. With FsmCoding ECodingType.Automatic, the state variable must have the name state. |
FsmTransitionHandler |
MyState_Xxxxx(MyEventClass event)
MyState_Xxxxx(FsmEvent event) |
Defines a transition handler method for a specific state and a specific event. The state must be passed as a string parameter to the attribute. With FsmCoding ECodingType.Automatic, the transition handler method must follow the naming convention MyState_Xxxxx(MyEventClass event). It is possible to define a default transition handler: with MyState_Xxxxx(FsmEvent event), the FSM catches all events which are not handled by the other transition handlers for this state. |
FsmStateHandler |
MyState_EntryState()
MyState_ExitState() |
Defines a state handler method. A state handler method is non-static and must have two and only two parameters: FsmEvent event and MyState oldState. The state must be passed as a string parameter to the attribute. The type of state handler must be passed as the second parameter: EStateHandlerType.Entry = state entry handler, EStateHandlerType.Exit = state exit handler. With FsmCoding ECodingType.Automatic, the state handler must follow the naming convention MyState_EntryState(), respective MyState_ExitState(). |
FsmEventHandler |
Xxxxx(MyEventClass event) |
Defines an event handler method for events defined by the event parameter in the signature of the method. A event handler method is non-static and must have one and only one parameter, derived from FsmEvent. With FsmCoding ECodingType.Automatic, the event handler must follow the naming convention Xxxxx(MyEventClass event). |
Sample 1: RTLibConsoleTest
This program is a console application and does nothing useful. There are two FSMs:
MyFsm1 |
Without attributes, using naming convention only |
MyFsm2 |
Using attributes only |
Sample 2: Dining Philosophers

Five philosophers sit around a circular table. Each philosopher spends his life alternatively thinking and eating. In the center of the table is a large plate of spaghetti. A philosopher needs two forks to eat a helping of spaghetti. Unfortunately, as philosophy is not as well paid as computing, the philosophers can only afford five forks. One fork is placed between each pair of philosophers and they agree that each will only use the fork to his immediate right and left. Philosophers are depicted in yellow when they are thinking, blue when hungry and green when eating.
Points of Interest
While programming FSM, I learned something about reflection and threading.
History
- December 1, 2003 - Initial version.
- December 23, 2003 - Added default transition handler and completed description.
- April 27, 2005 - Fixed some bugs and improved documentation.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 47 (Total in Forum: 47) (Refresh) | FirstPrevNext |
|
|
 |
|
|
For your interest in using statemachines in real systems look at www.steed.de. You can build UI based Aplication as Services or C/S applications with it. I decreases developmentime an programming efford. And you can easy monitor your running applicaton.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have used your framework for an automation project I am working on. It is working very well, and reduced my development time considerably. Many thanks for that.
The only problem I have run into is that some events I have are time critical (+/-20 milliseconds accuracy is needed), the FSM timer events are sometimes out of this range.
I noticed that you have SyncEvents, but I have not tried to use them. Can you explain more about what they are for and how they are used?
Is there a way to set a "priority" for certain events?
Thanks again and best regards.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Tash
Thank you for your feedback.
About the timer issue I will look into that problem sasp.
About SyncEvents: In the article on chapter "Implementing an FSM, step by step", Point 4, you will find the Note: "With Wait(), it is also possible to synchronize to the processing of a posted event if it is derived from SyncEvent. Fsm and EventBase have a constructor with a synchronized parameter." It is basically to synchronize to the treatment of the event. It is also possible to synchronize to the completion of an FSM.
I like your idea to introduce a "priority" to events. As soon as I have some time left, I will implement that. Do you think, "high" and "low" is sufficient or do we need more values?
Best regards Linus
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Linus,
Thanks for your reply. I had missed point 4 you mentioned above, thanks for pointing that out. Would this be the correct way to sync to the completion of an event?
private class mySyncEvent : FsmSyncEvent
then in a code section
mySyncEvent ev = new mySyncEvent(); PushEvent(ev); Wait();
Would this then wait until the event was processed? When does it continue? Is it at the completetion of the event handler? If the event caused a state transition, does the transition happen first?
As for the timer events, in my initial testing they seemed to always fire in a very timely manner. But the project has become more complex. There is a form which controls 2 FSMs. I added a timer control to the form object and it has an event which is firing every 100ms. This is not really a time critical process, just a time display for the user, and some logic to trigger some FSM events if certain conditions apply. Once this timer was added I noticed the FSM timer events were then taking slightly longer, I assume it is because the processor can not service them quickly enough with so many other things happening. That is why I was wondering about priorities, if there is a way to say certain events need to be a "high" priority that would be excellent. For my purposes just "high" and "low" would be fine.
Many thanks for you help and advice.
Best regards, Tash Robinson
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
> Would this then wait until the event was processed? Yes > When does it continue? Is it at the completetion of the event handler? Yes > If the event caused a state transition, does the transition happen first? Yes
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Concerning the timer problem: It is important not to "block" an event or transition handler. If such a handler is executing a time consuming operation, the event queue is not checked in the meantime. That means also, that timer event may elapse undetected. If an event handler has to execute a time consuming operation, it should - delegate it to another FSM on another processor (=thread), or - use an asynchronous variant of the op which sends back an event on completion
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
If you change the delegate signature of OnChangeForkState(int ForkHashCode,Fork.State state) to OnChangeForkState(Fork fork,Fork.State state) you will be able to directly register it with the Fork event ChangeState: fork.ChangeState += new Fork.OnChangeStateDelegate(OnChangeForkState); Add the line of computing hash code internally. This way you get rid of declaring m_ChangeForkStateDelegate, the delegate itself and the ChangeForkState intermediate which uses the the BeginInvoke internal function. The same applies to the Philosopher case. I liked your article and learned a lot. Thank You
Ilan
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
 |
|
|
Thank you for your finding. You are right, your solution is more elegant. I will change that in my test program for the next version. And I am honored that you enjoyed my aricle.
Linus
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Linus, In your examples you show handling a specific event in an FSM without states or with no transition handler for that event and the current state. However, I would appreciate an example showing how to handle such a situation within the context of specific states.
For example, let's say I have StateA and I have defined 3 events that are handled by transition handlers for StateA. However, if any other event is received while in StateA, I want to transition to StateB. This would only happen if the event is not one of the 3 already handled (i.e., a default case).
This handling needs to be specific for StateA. For example, if I have an analogous situation (a default case) in StateC, I might need to transition to StateF (not StateB as I did earlier).
The obvious way to do this is to use a switch statement inside the FSM's EventHandler but this doesn't seem very satisfactory. Can you give me some suggestions and an example?
Thanks! Mountain
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Mountain
You are right. My solution does not support a default transition handler for a specific state. The actual situation (Fsm::OnEvent): If FSM does not find a transition, it tries to find an event handler for this event. If it does not find an event handler, it calls the virtual method "OnFsmEventDefault"
I will enhance FSM this way, that the user will be able to define a default transition handler for every state. This transition handler will handle all events received in StateA where no transition handler is defined for. For automatic mode, the method name will be "StateA_DefaultTransition". The attribute will be [FsmDefaultTransitionHandler("StateA")]
Satisfied?
If you are patient, give me a few days to implement it. Otherwise, do it yourself.
Linus
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Linus, I think that will be an excellent enhancement for FSM. I will wait on you to implement it. However, when you get it done, I'll try to make the time to post an example showing FSM using this new feature. I think it could be a nice example for you. It will be a calculator implemented on FSM. Best regards, Mountain
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
// Viellecht könnte man diesen override dynamisch in Fsm // erzeugen!!!
This is in the code. It looks important. What is the english translation?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It is german and means: Probably it is possible to create this override dynamically. I felt that it is not so nice, that the user of Fsm has always write this override "GetCurrentState". The reason is, that the Fsm class has to know the current state. But the state enumeration is user-specific. Perhaps it is possible to generate this method dynamically by reflection. This issue is not so important, in spite of the 3 exclamation marks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Very nice Article; I must admit that I have not tried the code, I'm not in the .NET business But everybody really interested in state machines should read the book "Practical Statecharts in C/C++" from Miro Samek. It goes much more in detail (of course, it's a whole Book about the topic) and provides a framework for hierachical state machine as defined in the UML standard. And the author claims his code is production ready.
Andre
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
qf4net: Quantum Framework for .Net Hierarchical State Machine and Active Objects
"Here you can always find the latest version of the C# port of Miro Samek's excellent implementation of a hierarchical state machine and his Quantum Framework for active objects."
http://www.hessmer.org/dev/qhsm/
|
| Sign In·View Thread·PermaLink | 4.00/5 (1 vote) |
|
|
|
 |
|
|
That does look very nice indeed. I've scrapped my FSM implementation for Dr Hessmer's QF port however i'm curious about the BSD style license it employs. As its a direct port of Quantum Leap's framework which uses a dual license GPL + Commercial scheme, I'm wondering if his license is valid?
http://www.quantum-leaps.com/licensing/com.htm[^]
In any case, Quantum Leap's commercial licensing prices are very reasonable... well worth the time saving of developing a flexible, thread safe, and debugged FSM framework from scratch.
I'm going to put it through the paces in some test apps of my own and if everything checks out, I'm just going to focus my time on a gui designer\code generator for it.
-- modified at 5:00 Sunday 19th March, 2006
FYI, I got an email back from Dr Hessmer and I'm sure he wouldnt mind me relaying part of his reply. Here is the relevant answers by him, to the above:
"I explicitly checked the licensing situation with Miro Samek when I did the port. Your assumption is right: The C# port is solely covered by the BSD-esque license listed on my Web site.
Miro only started using the dual GPL and commercial license in later versions that he offers on his web site."
-- So there you have it. Its free to use for any purpose.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
When I run the ConsoleTest project, the order I see is: StateX_EntryState StateX_ExitState StateX_OnMyEventX
Why is the Exit before the transition?
Kathy.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This happends since the transition StateX_OnMyEventX is executed AFTER leaving StateX. The order is like this: 1. Enter state StateX (upon starting the FSM or as a reaction to an event A)--> StateX_EntryState 2. Another event B is received 3. Since there exists a transition handler for event B, the FSM leaves StateX --> call StateX_ExitState 4. Now the transition can be executed --> StateX_OnB, here, the new state StateY is defined 5. Enter state StateY
I unterstand that it is samewhat confusing, but on my opinion, the FSM has to leave the state before it can execute the transition (which usually defines a new state to enter). But I am curious about discussion about this subject since I am not sure in this point. The code to it you will find in fsm.cs, line 174
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Are you saying that the machine is "Stateless" while the transition occurs ?
It leaves a no-mans land. The potential for encountering it depends entirely on the length of transition. Should we therefore include transition states in our list ?
For example: Instead of two states: Idle, Running Use: Idle, Commencing, Running, Finishing where (threaded ?) processing is done during Commencing & Finishing
To my mind, machines ought not be able to exist "stateless".
If this is a silly question, please forgive my ignorance.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
No, the FSM is never stateless, except if you have not defined a state variable. The idea of a transition is, that it does not consume time. It is even a mistake to call a blocking operation within a transition handler, since the thread is not able to process any FSMs and events in the meantime. Time consuming operations have to be executed asynchronously. Your solution with additional states is a good approach. Another way is to define a second (sub-)FSM, controlling the process of your "during" transition. Or you send a timer event to your FSM, signalling the end of the operation.
There are no silly questions, just silly answers. I hope you are sadisfied by my answer.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
What are the applications for such a system? I've never heard of Finite State Machines, so I'm not sure why I would want to use one. Can you give some examples of real-world uses for this?
Thanks, Ceph
Skydive -- Testing gravity, one jump at a time.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Aside from the more well known uses of state machines, I've read about it being used to manage purchases on a retail website. (I always thought that was pretty cool.) Something similiar was demonstrated in an ASPToday article "Session and State Management in Distributed Web Applications".
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Tom Fischer wrote: Aside from the more well known uses of state machines
Hehe, well, the problem is, I don't know what the well-known uses are.
Skydive -- Testing gravity, one jump at a time.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Good point! 
If memory serves me right, managing TCP connections was the Gang of Four's state machine demo. If you consider how a computer handles a request tihs makes sense. It first looks at its current "state", such as open or closed, and moves to another state as the situation dictates.
BTW, MSDN had a good article that talked about the state machine design pattern - http://msdn.microsoft.com/msdnmag/issues/01/07/patterns/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|