Of States & Events: State Machines Explained
Having now been working with Workflow Foundation (WF) for several weeks; today I realized that I might be using State Machine workflows incorrectly - and there may be future consequences I would rather avoid. I am currently working on a workflow that essentially mirrors a business process with defined states: there are states in their process literally called State0, State1, State2, etc. When first deciding what kind of workflow to use - sequential or state machine - the choice seemed obvious. And I still think I made the right choice, basically.
However, State Machines have a bit of a limitation when it comes time to implement: the StateActivity components used to contain all constituent workflows in a state machine allow only 3 types of activities:- StateInitializationActivity
- EventDrivenActivity
- StateFinalizationActivity
My workflow is IIS-hosted and the first activity - State0 - contains a ReceiveActivity, which exposes a method accepting data form the caller via WCF and, more importantly to this discussion, implements IEventActivity. Using IEventActivity is a requirement for all activities contained by the EventDrivenActivity. So everything works fine there. But at some point in State0, I need to make a decision whether to advance to State1 or State2 and have adopted the IfElseActivity in concert with a pair of SetStateActivities to do this job.
Now, in designing the State1 and State2 sub-workflows, I probably should have used another EventDrivenActivity. But the number of activities one can place within the EventDrivenActivity is very limited and none of those available seemed to match my needs. Indeed, it seemed that it should be completely unncessary since the previous SetStateActivity already indicated what workflow I wanted executed next without any particular need for an event to be thrown. Frustrated by the lack of obvious choices, I settled on leveraging the StateInitializationActivity for the time being - and everything worked fine for a while.
But then State3 came along and suddenly, I had a point where I needed to introduced 2 EventDrivenActivities. I couldn't use the StateInitializationActivity here otherwise all workflow contained therein would be executed ahead of anything I placed in my EvenDrivenActivities. The second of these again uses a ReceiveActivity to accept a request to dehydrate a workflow and continue. But this time, I felt forced to use an event where none was really required since State2 transitioned to State3's first EventDrivenActivity successfully using a SetStateActivity. As a workaround I implemented a DelayActivity and behind it added other needed workflow elements.
As a result of the above experiences, I am uncertain about whether I've used WF correctly - despite the fact it is currently doing everything I need it to. Should I be using EventDrivenActivities where doubt was expressed above in place of the StateInitializationActivities? If so, does it makes sense I should need to create IEventActivity derivatives just to transition state when the SetStateActivity will otherwise do the job? (SetStateActivity appears to execute the first EventDrivenActivity listed within the StateActivity box when there's more than one.)
I hope I can prevail on someone out there to clear up my confusion on these points. My efforts to find articles on Workflow events has yielded a wealth of info on the HandleExternalEvent - which seems to have been made largely obsolete in the WCF/ReceiveActivity model introduced by .NET v3.5. At the very least, the literature my searches have turned up hasn't answered the above questions.
Perhaps you can!
Ross is a .NET developer based in Gatineau, Québec (Canada), working with the Government of Canada.
Answers
- Every addition of activity puts some extra load on the system. The binary size of workflow increases with each addition of activity and hence it would mean more memory, more CPU and more size of serialization/de-serialization. Adding a child workflow and using Send/Receive adds more complexity as well as a layer of more control.
But this should not stop us from building a good workable system. If it can work for you, do it.
Just in case you want to evaluate the performance of your workflow system, here's an excellent article on how to do it:
http://msdn.microsoft.com/en-us/library/aa973808.aspx- Marked As Answer byRoss Holder Thursday, October 22, 2009 9:25 PM
All Replies
- It seems that you need a Sequential Workflow rather than a State Machine. State Machine workflows are used where human intervention is expected and hence the workflow stays in a State until and unless a human triggered event is not received.
In case you have events that are self triggered, as it seems in your case, you should use a Sequential workflow. It seems that you need a Sequential Workflow rather than a State Machine. State Machine workflows are used where human intervention is expected and hence the workflow stays in a State until and unless a human triggered event is not received.
In case you have events that are self triggered, as it seems in your case, you should use a Sequential workflow.
Can I disagree? ;)
In my ealier diatribe, I suppose I forgot to mention that some of the states involve human intevention. State3, for example, requies that an agent supply additional data prior to transition to State4 or State5. But not all states require human intervention. I suppose, then, the short answer to my inquiry is simply that transition between states ought to be guilded by human intervention - and that such intervention ought to involve an event (like that thrown by the ReceiveActivity).
Would that be a fair characterization?
Ross is a .NET developer based in Gatineau, Québec (Canada), working with the Government of Canada.- Transition between states can be done by any eventdrivenactivity, which can be DelayActivity or external event like human intervention. In some cases we also design parent-child workflows, where one workflow (sequential or state) is a child of another workflow. May be you should experiment with such a scenario to eliminate the state(s) which are self driven.
- Yeah we've looked at that yesterday briefly. And it makes sense - one could imagine a "child" workflow being called via a SendActivity/ReceiveActivity combo, for example, which might work nicely. But I gotta tell ya would it ever be nice if one could blend human-instigated state transition with the non-human kind because, at least in this particular case, the state machine model would accomodate a design that'd map a lot more closely to the business processes we're migrating. (This isn't a new system we're building - it's an upgrade of a previous system to use Workflow Foundation.)
One thought that did occur concerning using the SendActivity/ReceiveActility to transition between states; of course one would be using WCF through IIS (in our case). Would there be a noticable performance difference between such a scenario and the alternative methods? (I am guessing not....)
Ross is a .NET developer based in Gatineau, Québec (Canada), working with the Government of Canada.- Edited byRoss Holder Thursday, October 22, 2009 3:04 PMText added for clarification
- Every addition of activity puts some extra load on the system. The binary size of workflow increases with each addition of activity and hence it would mean more memory, more CPU and more size of serialization/de-serialization. Adding a child workflow and using Send/Receive adds more complexity as well as a layer of more control.
But this should not stop us from building a good workable system. If it can work for you, do it.
Just in case you want to evaluate the performance of your workflow system, here's an excellent article on how to do it:
http://msdn.microsoft.com/en-us/library/aa973808.aspx- Marked As Answer byRoss Holder Thursday, October 22, 2009 9:25 PM
Every addition of activity puts some extra load on the system. The binary size of workflow increases with each addition of activity and hence it would mean more memory, more CPU and more size of serialization/de-serialization. Adding a child workflow and using Send/Receive adds more complexity as well as a layer of more control.
But this should not stop us from building a good workable system. If it can work for you, do it.
Just in case you want to evaluate the performance of your workflow system, here's an excellent article on how to do it:
http://msdn.microsoft.com/en-us/library/aa973808.aspx
Thanks so much for this exchange! Hopefully the subject matter helps others remedy similar confusion about the State Machine Workflow and its application - particularly in real-world scenarios involving mixed types of state transition. At the very least, it's helped me feel a lot more confident about the decisions I'm making with respect to my current design(s).
Also very much appreciate the link - the article was very interesting indeed!
Gratefully,
Ross is a .NET developer based in Gatineau, Québec (Canada), working with the Government of Canada.


