none
Understanding WF 4 State Machines

    Question

  • Hello,

    I am trying to understand state machines in WF 4. I would like to be able to, from the outside, trigger a transition on the state machine.

    First, I  created a state machine workflow with a number of states, some of which, have more than one transitions. I also created an enumeration for mapping the states and another one for mapping the transitions. On each of the states, I am creating a bookmark, using a NativeActivity-derived activity, with the state's name.

    What shall I place on each of the transition's triggers? Shall I also create a bookmark using the originating state's name, or, instead, the transition's? Or the same name for all transaction's triggers?

    Thanks!

    RP

    Wednesday, May 16, 2012 8:41 PM

Answers

  • Hi,

    The best way to have a state machine wait on events from the user/host application is to use activities that wait on bookmarks in the trigger of the transition. When the hosts resumes the bookmark, the condition (if present) in the transition will be evaluated, and if it evaluates to true then the transition action (if present) will occur, and then he state machine will transition to the next state. To see an example of this, see the How to create a state machine workflow portion of the WF4 Getting started tutorial. To see how to create the custom activity that creates the bookmark that waits for use input, see the first step in the tutorial, How to create an activity, and then to see how the host can resume the bookmark, see How to run a workflow. You can watch a video walkthrough and demo of the tutorial and download a completed example here: http://code.msdn.microsoft.com/Windows-Workflow-164557c3

    This shows you an example of state transitions with no trigger, and also shared trigger transitions (multiple possible transitions based on a common trigger)

    Take a look and see if this helps provide the info that you need.

    Thanks,

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

    Thursday, May 17, 2012 3:59 PM
    Moderator
  • Yes, this is the correct answer. You should allways use a bookmark, because your waiting activity whon't consume resources, and the workflow host will be allowed to persist the instance, while waiting for the bookmark to be resumed.

    The bookmark is defined by name, so your activity, should create a bookmark with a given known name, and just wait for it to be resumed. On your form, you must know the bookmark name, and on a given user action you just have to resume it.

    You can get a simple example here: http://msdn.microsoft.com/en-us/library/dd489442.aspx

    Friday, May 18, 2012 9:24 AM
  • Ricardo,

    You might find the following "Hands on Lab" helpful:

    Windows Workflow Foundation (WF4) - Introduction to State Machine Hands On Lab

    It describes all the details that you would need.

    -Hani

    Monday, May 21, 2012 8:56 PM

All replies

  • Hi RP,

    You can have shared transion triggers on Stats .. And on each Trigger you can have condtion to decide next activity to be executed.

    See the triggers are starting from the same point .. and on each trigger you can have condition to define the flow of your workflow. Ne need to put anything on transition trigger to move the workflow. Please let me know if this does answer your query.

    Thanks

    Madhur


    MB


    Thursday, May 17, 2012 4:16 AM
  • Hi, Madhur, thanks for your answer!

    Yes, I know about shared triggers and conditions. I think I didn't explain properly: I want my state machine to be "controlled" from the outside, say, a web page. So, I want to be able to switch from the current state to the next state, by performing some action on a web page, that will eventually trigger something on the state machine. From what I've seen, this trigger is accomplished by resuming a bookmark, am I right?

    Thanks,

    RP

    Thursday, May 17, 2012 7:58 AM
  • Hi RP,

    In that case you can have and InArgument (say String type) and check value of that action in the shared triggers.

    Let's say InArgument is "ActionTaken" of type string . which you can pass from outside when any action is taken on the webpage (when you resume your workflow )  and check value of that in Shared Triggers

    you can have condition like

    ActionTaken = "Submit1" --  for Triggers 1

    ActionTaken = "Submit2" -- For Triggers 2

    Is this make sense ?  Am i going in right direction?

    Thank,

    Madhur


    MB

    Thursday, May 17, 2012 9:43 AM
  • Hello, again!

    But, how can I set the ActionTaken argument on the state machine instance? And, do I need a trigger on every transition, besides the condition?

    Thanks!

    RP

    Thursday, May 17, 2012 10:00 AM
  • No you dont need any trigger on any transition ,Let me try to to make it more clear.

    While designing workflow (IN VS or rehosted designer) there a

    click on the Argument tab on the WF designer and create an InArgument of string type Having name "ActionTaken".


    MB

    Thursday, May 17, 2012 11:31 AM
  • Madhur,

    Thanks, I am already familiar with arguments; what I asked was, how do I set the value of the argument, from the outside of the state machine? I already know how to do it from inside, from an activity.

    So, the conditions on every transition are continually being evaluated... like in an active wait? And what decides where to go next is the current value of the argument... that makes sense, but does it need to be thread-safe, for example?

    What are the common practices, for example, has anyone considered usage of AutoResetEvents, or something like that?

    Once again, thanks for your help!

    RP

    Thursday, May 17, 2012 1:15 PM
  • OK.

    Follow this link to pass argument from outside  here

    AutoResetEvent syncEvent = new AutoResetEvent(false);
    
    Activity wf = new WriteLine();
    
    // Create the dictionary of input parameters.
    Dictionary<string, object> inputs = new Dictionary<string, object>();
    inputs.Add("Text", "Hello World!");
    
    // Create the WorkflowApplication using the desired
    // workflow definition and dictionary of input parameters.
    WorkflowApplication wfApp = new WorkflowApplication(wf, inputs);
    
    // Handle the desired lifecycle events.
    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        syncEvent.Set();
    };
    
    // Start the workflow.
    wfApp.Run();
    
    // Wait for Completed to arrive and signal that
    // the workflow is complete.
    syncEvent.WaitOne();

    

    MB

    Thursday, May 17, 2012 1:49 PM
  • OK, so a possibility would be:

    - Pass an AutoResetEvent into a state machine activity by using an extension or an input parameter;

    - Have all transitions' triggers wait on this event, by using a simple custom activity;

    - Have a condition on all transitions that checks for a specific value on each transition, to allow continuing;

    - From the outside, when I want a transaction to occur, I resume a bookmark, passing it the specific value that validates one of the conditions on the triggers;

    What do you think?

    Thanks,

    RP 

    Thursday, May 17, 2012 2:49 PM
  • Hi,

    The best way to have a state machine wait on events from the user/host application is to use activities that wait on bookmarks in the trigger of the transition. When the hosts resumes the bookmark, the condition (if present) in the transition will be evaluated, and if it evaluates to true then the transition action (if present) will occur, and then he state machine will transition to the next state. To see an example of this, see the How to create a state machine workflow portion of the WF4 Getting started tutorial. To see how to create the custom activity that creates the bookmark that waits for use input, see the first step in the tutorial, How to create an activity, and then to see how the host can resume the bookmark, see How to run a workflow. You can watch a video walkthrough and demo of the tutorial and download a completed example here: http://code.msdn.microsoft.com/Windows-Workflow-164557c3

    This shows you an example of state transitions with no trigger, and also shared trigger transitions (multiple possible transitions based on a common trigger)

    Take a look and see if this helps provide the info that you need.

    Thanks,

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

    Thursday, May 17, 2012 3:59 PM
    Moderator
  • Yes RP..  Use bookmark to persist/Resume workflow.

    Thanks,

    Madhur


    MB

    Friday, May 18, 2012 4:20 AM
  • Yes, this is the correct answer. You should allways use a bookmark, because your waiting activity whon't consume resources, and the workflow host will be allowed to persist the instance, while waiting for the bookmark to be resumed.

    The bookmark is defined by name, so your activity, should create a bookmark with a given known name, and just wait for it to be resumed. On your form, you must know the bookmark name, and on a given user action you just have to resume it.

    You can get a simple example here: http://msdn.microsoft.com/en-us/library/dd489442.aspx

    Friday, May 18, 2012 9:24 AM
  • Ricardo,

    You might find the following "Hands on Lab" helpful:

    Windows Workflow Foundation (WF4) - Introduction to State Machine Hands On Lab

    It describes all the details that you would need.

    -Hani

    Monday, May 21, 2012 8:56 PM
  • Hello, again!

    Thank you all for your replies! I have been out for some days, now I would like to resume this thread.

    The example in the WF4 Getting started tutorial is interesting, however, I still have some questions:

    - What if I don't want my state machine to be input-driven, that is, not reading something from the keyboard, a form, etc? What should I place in the trigger instead of the ReadInt? Should I go for Manual/AutoResetEvents?

    - By resuming a bookmark I make the state machine "jump" to a previously created bookmark, no matter what the current state is?

    - Is ResumeBookmark the only way to send "commands" to the state machine? That is, not considering global events and variables?

    - Is it possible, on a state (or, better, on a custom activity inside a state) to know the possible transitions from the current state?

    Once again, thank you all for your time and patience!

    RP

    Friday, May 25, 2012 1:42 PM
  • Hi Ricardo,

    Technically it's the completion of the trigger activity which triggers the state machine, not ResumeBookmark. You could use a non-blocking activity such as sequence as a trigger. But if you do that it would trigger a transition instantly - and since it would now always follow that transition, you would lose all ability to branch and choose which state to go to next.

    A bookmark basically is giving your state machine the ability to decide to do something else, instead of take an unconditional linear flow like a Sequence.

    Tim

    Friday, May 25, 2012 3:28 PM
  • Hello, Tim!

    Yes, I understand that, but my questions still remain unanswered! :-)

    From what I understand, I must use an activity that has a return value and blocks until it is set (unlike NativeActivity, but like NativeActivity<T>), and upon resuming, I set the return value to the one that came from the ResumeBookmark, thus causing it to proceed. Am I correct here?

    Thanks,

    RP

    Friday, May 25, 2012 3:58 PM
  • The activity doesn't need a return value. If it has one, the the return value doesn't matter.

    What matters is whether the activity completes or not. As soon as one activity completes, any competing trigger activities get cancelled.
    Tim

    Friday, May 25, 2012 8:02 PM
    Moderator