WF Guidance: State Machine
Status: Final Draft, .NET 4 Beta 2
Last Modified: 12/25/2018 4:05:20 PM
The audience for this paper includes users of Windows Workflow Foundation in .NET Framework 3.0 and 3.5 (WF3)that currently utilize the StateMachine activity as well as the community of workflow developers who are learning about the control flow constructs (composite activities) that will ship with the new Windows Workflow Foundation model introduced in .NET 4 (WF4).
WF4 (currently in Beta release) does not include a StateMachine activity. This paper presents some alternative approaches to modeling state machines that let you accomplish a large number of WF3 state machine scenarios. An out of the box state machine activity in WF4 is high on the list of features we are considering in subsequent WF releases. Taking an honest look at the approaches in this paper and providing feedback about whether they satisfy your requirements will be critical in determining the shape and timing of a WF4 state machine activity. In addition we welcome feedback on the WF3 StateMachine activity. Please use this forum post ( to provide feedback.
Please see the document “WF Migration Overview” for a broader discussion of WF3 to WF4 migration, and links to related WF3 -> WF4 documents. The latest version of these documents can be found at
The information contained in this document relates to pre-release software product, which may be substantially modified before its first commercial release. Accordingly, the information may not accurately describe or reflect the software product when first commercially released. This document is provided for informational purposes only, and Microsoft makes no warranties, express or implied, with respect to this document or the information contained in it.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
2009 Microsoft Corporation. All rights reserved.
Microsoft, Windows, Visual Studio, and the .NET logo are trademarks of the Microsoft group of companies.All other trademarks are property of their respective owners.
WF Guidance: State Machine (.NET 4 - Beta 2 Release)Page 1
When WF first shipped with the .NET Framework 3.0, the StateMachine activity was one of several “out of the box” composite activities. WF3 also allowed developers to write their own custom composite activities.
WF4 (currently in Beta release) also ships with a set of “out of the box” composite activities. This set includes many that existed in essentially the same form in WF3 (e.g. Sequence, Parallel). The WF4 set does not include some composite activities that did ship in WF3; among these are StateMachine. The WF4 set also includes a few new composite activities, notably Flowchart, Switch, DoWhile, ForEach, etc. WF4 continues to allow developers to write their own custom composite activities.
The table below summarizes the out of the box composite activities available in WF.WF3 Composite Activity / WF4 Composite Activity / Comments
- / Flowchart / New in WF4.
Sequence / Sequence
Parallel / Parallel
While / While
DoWhile / New in WF4.
IfElse / If
Switch / New in WF4.
Listen / Pick
Replicator / ForEach, ParallelForEach / The WF3 Replicator activity has a property that determines whether or not execution is parallel.
StateMachine / - / No direct analog in WF4.
ConditionedActivityGroup / - / No direct analog in WF4.
EventHandlingScope / - / No direct analog in WF4.
WF Guidance: State Machine (.NET 4 - Beta 2 Release)Page 1
The Flowchart Activity
Since the release of WF3, customers have given us feedback about what they like and don’t like. One common point of feedback from customers using WF3 is that “we want the simplicity of Sequence, Parallel, etc. but the flexibility of StateMachine.” When we dig deeper to get at the scenario behind this sentiment, we often find that customers have a process (or a portion of a process) that is often quite sequential in nature but which requires “loopbacks” under certain circumstances(for some customers the circumstances are“exceptional” in nature while for other customers they are “expected” but it really doesn’t matter to this discussion).
We believe that the Flowchart activity squarely addresses this (rather large) class of scenarios. Let’s look at the details.
A Flowchart is a set of nodes and arcs. The nodes are activities. The arcs describe potential execution paths through the nodes. A Flowchart has a single path of execution; that is, it does not support split/join semantics that would enable multiple interleaved paths of execution. The diagram below shows the same Flowchart as a conceptual model (left) and a WF implementation in the WF4 designer (right).
Given this behavior, it is trivial to model a sequence of steps using a Flowchart:
We could of course also model this using a Sequence activity.
Ourscenario might, under some conditions, require execution to “loop back” or “branch” from step C back to step A. Now things get interesting. If we have built our workflow using the Sequence activity, we can accomplish this using sometraditional branching and looping (If and While activities) like so:
If we are using a Flowchart, we can model this more straightforwardly by adding a decision node. As you can see, the ability to use an arc to loop back to the prior step makes this much more natural to the individual designing the workflow.
Now let’s imagine we require a second “loop back” from D back to B. Again, we can do this with our Sequence but things are certainly starting to get messy. In addition to multiple loops and branches, we must craft the conditions governing these paths of execution quite carefully in order to achieve the correct solution.
With Flowchart it is pretty natural to model this, since it’s exactly what Flowchart was designed for.
Moving beyond this simple example, let’stake a look at something more specific. The Ordering State Machine sample ( which shipped with the WF3 documentation, demonstrates a sequential process which requires two “loopbacks,” so a StateMachine workflow was chosen due to the complexity of implementing the “loopbacks” using a Sequence.
This scenario can be modeled easilyusing a Flowchart in WF4:
Hopefully, this quick tour of Flowchart piques your interest, and demonstrates that a wide range of scenarios are modeled naturally using Flowchart. If we have done things right, you now have “the simplicity of Sequence, Parallel, etc. but the flexibility of StateMachine” at your fingertips.
When designing processes, most of us think in terms of flowcharts – whether we are working in Visio or scribbling on a whiteboard. For this large group of scenarios, the Flowchart activity is a conceptually cleaner representation than a state machine, and customers have so far found the WF4 workflow to feel simpler and more natural (as is the case above). However, this is not to say that every state machine should be a flowchart, and sometimes a true state machine model (which is currently not available out of the box in WF4) is the most natural choice.
Modeling State Machines in WF4
In the preceding section we discussed the use of Flowchart as a way to describe a sequential execution path with “loop backs.” Although applicable inmanyscenarios, this approachisn’t the right one in all cases.
In this section, we will describe some other common patterns that can be followed to represent state machines using out of the box activities available in WF4.
Let’s start with the following example of a stopwatch state machine.
The stopwatch has four states: On, Off, Started, and Stopped. It has three events: off, start, and stop. Work is executed on the transitions from one state to another: transitioning into the Started state causes atimer to be triggered. Transitioning from Started to Stopped causes the timer to be stopped.
This program can be implemented in WF3using a StateMachine activity as shown below. For a full implementation, please see the StopWatch35 sample code which accompanies this paper.
Let’s now consider how to design this workflow in WF4.
Note: This intentionally simple scenario was selected in order to clearly illustrate the high-level patterns that you can use in modeling state machines in WF4. We realize that we have omitted commonly-used WF3 features (such as nested states and conditional transitions), which may introduce additional complexity when being modeled in WF4. Even though we don’t specifically address these features they can be modeled using the approaches we are about to present.Subsequent releases of this document may provide detailed guidance on how to model these specific features.
Solution Based on a Single Pick Activity
If we pivot around the three allowed events (off, start, stop), we can construct an event-processing loop, which listens for all three events at any given idle point in the workflow. Looking at the control-flow activities available in WF4, the While activity was a natural choice to accomplish the looping functionality. Inside our loop we need a way to listen for events and execute some logic when a given event is received. The Pick activity fits well here since it gives us much flexibility in modeling multiple alternative paths of execution. Itcontains a branch for each event (the event is called the branch trigger) and an activityto execute when that branch is triggered. So by wrapping a Pick activity inside a While activity we have implemented the event-processing loop functionality.
Now we have a mechanism that listens for incoming events, but it’s time to put the “state” in “state machine”. We create a local variable of type Sting (named “currentState”), and set it to the name of the state we are currently in. The initial value of the variable is set to “on” since that is the start state of our state machine.
Now we have the two key pieces to decide what actions to execute at any given point in the state machine: the event that was received and the current state of the state machine. For example, if the current state is “started” and we receive the event “stop” we want to execute the action “stop internal clock” and set the current state to “stopped”. To implement this given our existing event-processing loop (a Pick inside a While), we will use a Switch activity inside every branch of the Pick activity, where the “currentState” variable will be the expression we are switching on. Every case of the Switch will generally contain: (a) the set of activities to execute and (b) an Assign statement that sets the value of the “currentState” variable to cause the state machine to transition to its next state.
This is outlined in the diagrambelow;the code is available in theStopWatch40SinglePicksample accompanying this paper.
Note: This diagram (and some others further on in this document) was built using a graphical editor instead of the built in WF4 designer to make it as simple and clear as possible. You can easily recreate this workflow and achieve identical functionality by dragging activities out of the WF4 Toolbox onto the design surface and composing them to resemble the above layout.
Some considerations when using this approach:
- There is a unique place where we listen for every possible event, which minimizes the repetition oflistening logic (Receive activity, create bookmark, etc) where we accept external data into the workflow. This becomes important in scenarios where the same set of events is used multiple times in the state machine. Since we have one location where we listen for any given event (the trigger of the pick branch), there is no duplication of the listening logic.
- The structure of the workflow does not enforce the events that are valid in a given state. Since all events are accepted in all states, it forces the workflow author to throw exceptions (or take other appropriate action) when an invalid input is received (this is marked by the Invalid transition blocks in the diagram).
- In state machines where each event is used only once or twice, this model might not be the best fit, since we get no benefit from centralizing the listening logic. The additional overhead of having to handle invalid events (see the previous point) makes this approach less practical than the alternatives we are about to present.
- One of the reasons we choose WF to model state machines is due to its power to express them in a way that feels natural to us. The way we partition our states and even the way we position them on our design surface in WF3 is meaningful as it helps us reason about the way the state machine executes. In the pattern we just presented some of this expressive power is lost since states and transitions are not as obvious upon quick inspection of the workflow. This becomes more apparent as the size of the state machine grows.
Solution Based on Multiple Pick Activities
In some sense this approach is the inverseof the event-driven approach. The first pivot in our loop is no longer the event but the current state of the state machine; this may make this model easier to think about.The state machine is modeled as a While loop with a Switch activity (the variable again being “currentState”), which contains one case for each state of the state machine. We need two pieces to decide what action to execute – the state we’re in and the event that was raised – and we now have the first piece. To get the second piece we need to listen for events inside each case of the Switch activity. To accomplish that we use a Pick activity with branches corresponding to the events that can trigger transitions in that given state. Once an event is received, any work associated with that transition is carried out, and the state machine transitions to the next state. Similar to the previous model, the transition happens by setting the value of the “currentState” variable.
This is illustrated in the diagram below; the implementation is available in the StopWatch40MultiplePicksample distributed with this paper.
This approach is characterized by the following:
- It presents a state-centric approach that in some cases will feel more natural than the event-oriented approach presented in the previous section
- Unlike the previous approach, the structure of the state machine prevents it from accepting events that are invalid in a given state, so there is no need to add logic to handle invalid transitions.
- There can be more than one location in the program where we listen for the same event, which can cause duplication of event handling logic. This makes the approach impractical when dealing with state machines where we listen for the same event in multiple places. We can work around this limitation by creating a custom activity that contains the shared logic.
- Similar to the previous approach some of the expressive power of a WF3 state machine is lost.
Solution Based on Flowchart
The previous two solutions rely on a loop to manage the outermost control flow andthe actual states and transitions are not explicit when visually inspecting the workflow. The nextapproach we will exploreis very similar to the state-driven model shown above, but leverages the power of Flowchart to express non-linear control flow (transitions), and states as discrete chunks of workflow logic.
Just as in the state-driven model, the heart of a“state” in this approach is a Pick activity with a branch for every event that is valid in the current state. Inside each branch of the Pick activity, the next state is determined (by setting the “nextState” variable), and any work on that transition is carried out. Each “state” also logically contains a FlowSwitch activity, which uses the “nextState” variable to decide where to transition. This mechanism replaces the top-level While and Switch activities of our previous approaches.
This example is illustrated in the following diagram and also in the StopWatch40Flowchart sample which accompanies this paper. In the diagram, the implicit “states” made up of a Pick activity and a FlowSwitch activity are marked by a light grey outline, although these “states” do not exist as activities in the workflow.
This approach is characterized by the following:
- Just like the state-driven model, this model is characterized by state-driven design, but necessitates the duplication of event activities and associated logic. The duplication can be avoided by creating the appropriate custom activities and reusing them.
- In this model the notion of states (a Pick and a FlowSwitch ) and transitions is more apparent, so we regain some of the expressive power of the WF3 state machine.
Let’s recap what we covered here. We introduced the Flowchart activity and discussed how some state machine scenarios can be more naturally expressed as Flowcharts. We then presented three other approaches which can be used to describe state machines.
Even after presenting these alternatives, it is still possible that you have a state machine scenario that cannot be adequately modeled in WF4 using out of the box activities. To varying extents all of the approaches we presented dissolve the clear notion of nodes and arcs and replace them with less intuitive notions such as listener loops and switches.
There are two potential directions you can consider in this situation:
- Writing a custom state machine activity: The WF activity model provides you with rich extensibility to construct the perfect control flow mechanism for your scenarios. WF4 comes with a significantly improved activity model that you can use to write your own StateMachine activity.Implementing a custom state machine may be easier than you think using WF4.
- Waiting: You can wait for a subsequent WF release that contains a StateMachine implementation out of the box.
We are keenly interested in understanding your scenarios and ideas, and helping you accomplish your goals on WF4. The final shape and the timing of a StateMachine activity will strongly be influenced by the feedback you provide.We’d appreciate any positive or critical thoughts you may have on the alternatives outlined above, as well as your experiences with StateMachine in WF3, and we look forward to continued dialogue about the requirements you havefor a new StateMachine activity.