|Products Purchase Publishing Articles Support Company Contact|
Articles > .NET > Introduction to StateCoder
If you are new to State Machines, please take the time to read our article An Introduction to State Machines. It will help you understand what follows.
What is a StateCoder State Machine?
A state machine in StateCoder is made up of classes that you define that inherit from base classes in the Desaware.StateCoder namespace. The principle is exactly the same as that used to create other .NET classes such as forms, controls and web pages.
The StateMachine object.
In StateCoder a state machine is any object that inherits from the class Desaware.StateCoder.StateMachine or Desaware.StateCoder.UnmanagedStateMachine.
Most of your state machines will derive from Desaware.StateCoder.StateMachine, meaning that it is managed by the StateCoder framework. That means the framework will be responsible for watching for and sending messages, managing threading, synchronization, exceptions and performing various other tasks.
The most important part of defining your StateMachine class will be defining the states. This is typically done using attributes. The ContainsState(statename) attribute defines the states for the state machine. You can also pass an array of state objects to the state machine when it is created.
Your StateMachine object is the only object that will be accessible to your main program. You might define properties or methods if you need to specify any information to the state machine before it starts. You might also add members for any data that needs to be shared by the states in the state machine.
Then you'll call the Start method to start the state machine running.
The StateMachine object has additional capabilities. It can raise events when the state machine enters the end state. It can provide a waitable object for you to wait for completion. It has a hook capability that allows you to monitor state transitions. And, of course, you can build in additional features as well.
But the key thing to remember is that all access to your state machine should be through this object. This object provides much of the encapsulation that helps StateCoder simplify use of state machines (and, of course, does a lot behind the scenes so that you don't have to).
State machines can signal the calling program that they have reached the end state using an event or a wait handle.
The State objects
Each state in your state machine is represented by a class that inherits from the Desaware.StateCoder.State or Desaware.StateCoder.DynamicState class (the latter allows you to define states dynamically and thus define state machines at runtime.
One of your state classes must have the "InitialState" attribute, and one the "FinalState" attribute. Each state has a member that points to its state machine, so you can access any data common to the state machine. Each state overrides the method "MessageReceived" to process incoming messages. Each state calls the "NextState" method to specify the next state. It can also override the "EnterState" method that is called when the state is entered (immediately after another state calls NextState). A state object can also process incoming exceptions.
Now here's the cool thing: Once you've created a state machine, you are guaranteed that all messages will come into that state machine on the state machine's thread. You're also guaranteed (obviously) that your state machine will always be in a particular state. This means that unless you go out of your way to create a new thread within the state machine, the only possible area for multithreading synchronization problems are on the public properties of your state machine object. The states themselves are inherently self synchronizing.
But what if you think you do need a new thread inside a state machine? No problem - just create another state machine! StateCoder state machines can use other state machines. This is important, because it means that instead of creating big complex state machines (and their corresponding large complex state diagrams) you'll tend to create smaller state machines that call each other.
Desaware's StateCoder defines a message as a .NET object, which means it can be anything you wish based on the needs of the state machine. Messages are generated by objects that implement the IMessageSource interface. This interface includes methods that allow you to determine if a message is ready, to retrieve a message, and to retrieve a wait handle (System.Threading.WaitHandle) that will be signaled when a message is ready.
StateCoder includes a variety of base message source classes, including a generic message source that can wrap any user defined message, and an AsyncResultMessageSource class that works with any .NET class that follows the standard .NET asynchronous call design pattern.
Message sources are a key factor in improving the thread safety of a StateCoder state machine, because while the signaling event for the message may be created on any thread, the message itself will always be processed on the state machine's own thread - thus eliminating a huge potential source of subtle multithreading problems.
Every state machine can use as many message sources as it needs. Message sources can be defined for the entire state machine, or can be changed for each state.
Another important features is that every StateCoder state machine is itself a message source! A message is considered ready when the state machine enters its end state.
This is just a quick summary of the features of StateCoder. There's a lot going on behind in the framework to make sure that the state machines use minimal system resources. While you can create state machines to run in their own threads, well designed state machines (especially those that use asynchronous operations) will typically run on the StateCoder thread pool. This is essential for scalability - threads are expensive system resources.
What will you do with StateCoder?
The best way to learn about StateCoder is to download the demo from http://www.desaware.com. This is a fully functional demo that includes all of the documentation. It's only limitation is that you have to run it from within the Visual Studio environment. It won't run from a standalone executable.
We believe that StateCoder will help you create better .NET code more quickly, regardless of whether you are building standalone applications, web services or ASP.NET applications. If you are new to state machines, then you will find the design patterns you learn with StateCoder will become an indispensable tool for all your programming efforts, even when you aren't using the StateCoder framework.
For notification when new articles are available, sign up for Desaware's Newsletter.
|Products Purchase Articles Support Company Contact