StateMachine invoke SequentialWorkflow

Hi together,

I am using a state machine workflow which invokes another sequential workflow. The sequential workflow gets called but after the sequential workflow has finished, the parent workflow (which is a state machine) switches to the completion state.

Example:

Sequential Workflow
^
|
State A ---> State B ----> State C ----> Completion State


As you can see in the sample "State B" invokes "Sequential Workflow". And now when the sequential workflow gets finished, the parent state machine switches to the completion state
instead of "State C".

Any ideas what's wrong here

Cheers,
Franz


Answer this question

StateMachine invoke SequentialWorkflow

  • Jamie Clayton

    Serge,
    Your advice is extremely good. I went and implemented this per your code. I data bound the GUID to shut down to the GUID that was launched in the designer, as you mentioned. I signal the event that will cause the sequential workflow to stop using my external data exchange service. That then invokes the shutdown service. The problem is that from my main program, I signal the event to the data exchange service and everything seems fine... but, when the shutdown service goes to grab the guild to shutdown, it is set to Guid.Empty.

    Any thoughts on why that might be


  • Philip Jaques

    Hi Kevin,

    To summarize, I suggest 2 activities + 1 service:

    1°an activity for starting a workflow: LaunchWFActivity:

    2°a service for killing a workflow: WFShutdownService

    3°an activity for killing a workflow: ShutdownWFActivity ; this activity calls the following service ( WFShutdownService )

    4°DataBinding ShutdownWFActivity to LaunchWFActivity on the generated Guid

    5°in your case using a ListenActivity waiting for the event

    1° an Activity for starting a workflow

    ---------------------------------------------------------------------------------------

    public partial class LaunchWFActivity: Activity
    {
    public static DependencyProperty LaunchedWFGuidProperty = System.Workflow.ComponentModel.DependencyProperty.Register("LaunchedWFGuid", typeof(Guid), typeof(LaunchWFActivity));

    [Description("This is the description which appears in the Property Browser")]
    [Category("This is the category which will be displayed in the Property Browser")]
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public Guid LaunchedWFGuid
    {
    get
    {
    return ((Guid)(base.GetValue(LaunchWFActivity.LaunchedWFGuidProperty)));
    }
    set
    {
    base.SetValue(LaunchWFActivity.LaunchedWFGuidProperty, value);
    }
    }
    public LaunchWFActivity()
    {
    InitializeComponent();
    }
    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    {
    IStartWorkflow startWorkflow = executionContext.GetService(typeof(IStartWorkflow)) as IStartWorkflow;
    LaunchedWFGuid = startWorkflow.StartWorkflow(typeof(Workflow2), null);
    return ActivityExecutionStatus.Closed;
    }
    }

    2°A service for killing a workflow : this service will be called by the ShutdownWFActivity (see below)

    ---------------------------------------------------------------------------------------------------------------------

    class WFShutdownService : WorkflowRuntimeService
    {
    public void ShutDownWorkflow(Guid workflowGuidToShutdown)
    {
    WorkflowInstance wi= this.Runtime.GetWorkflow(workflowGuidToShutdown);
    wi.Terminate("normal shutdown");
    //wi.Abort();
    }
    }

    ------------------------------------------------------------------------------------------------------------------

    3°An Activity for killing a workflow ;


    public partial class ShutdownWFActivity: Activity
    {
    public static DependencyProperty WFToShutDownGuidPropertyProperty = System.Workflow.ComponentModel.DependencyProperty.Register("WFToShutDownGuidProperty", typeof(Guid), typeof(ShutdowWFActivity));

    [Description("This is the description which appears in the Property Browser")]
    [Category("This is the category which will be displayed in the Property Browser")]
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public Guid WFToShutDownGuidProperty
    {
    get
    {
    return ((Guid)(base.GetValue(ShutdowWFActivity.WFToShutDownGuidPropertyProperty)));
    }
    set
    {
    base.SetValue(ShutdowWFActivity.WFToShutDownGuidPropertyProperty, value);
    }
    }
    public ShutdowWFActivity()
    {
    InitializeComponent();
    }

    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    {

    WFShutdownService myservice =executionContext.GetService<WFShutdownService>();
    myservice.ShutDownWorkflow(this.WFToShutDownGuidProperty);
    return ActivityExecutionStatus.Closed;
    }
    }

    4°ShutdownWFActivity::WFToShutDownGuid property can be databound
    to a LaunchWFActivity::LaunchedWFGuid property in the designer.

    5°Now you can trigger the ShutdownWFActivity after a specific event (in your question you asked for an HandleExternalEventActivity) by using a listenActivity.



  • Amit V

    you probably used InvokeWorkflowActivity which is asynchronous;

    For a synchronous workflow call, read this :

    http://www.masteringbiztalk.com/blogs/jon/PermaLink,guid,7be9fb53-0ddf-4633-b358-01c3e9999088.aspx

    Serge



  • averge joe

    HI,

    I have done the same scenario like yours and i would suggest to do this to launch the sequential WF using a Custom activity(say Launch WF Activity) and in the execute acitivity method of that activity,you just call an external method which inturn will call the createworkflow method in your WF Manager class.Its bit tough but it works excellent!And in the state finalization activity in the state you launch the Sequential WF, you put a custom activity(Handle External Base) which waits for the completion of the sequential WF we launched from that state!

    Hope this helps..

    Sunath



  • Zapp

    I fixed it. I promoted the bindable property, and then bound the shutdown activity to the newly promoted property and now it works like a charm.


  • ceasor123456

    workflowInstance2 can be cached in the host, the calling workflow or in a service.

    Serge



  • musafir-a Voyager

    I was just about to post that I want to do the same thing here, but with a twist of lymon.

    What I want is for my state machine workflow to spawn the sequential workflow asynchronously (this workflow will be running in a while loop and never shut itself down on its own). When an external event is received, I want the workflow to stop the spawned sequential workflow, regardless of what state its in, and do something else.

    Any thoughts on how to implement this I know how to implement it as a "hack", but I think there's got to be a more elegant approach than what I'm doing.


  • Mike Greene

    Could you please provide a couple lines of code showing how to activate the child workflow, as well as how to shut it down as a result of a HandleExternalEvent activity

    Thanks!


  • Emy_P

    I have no idea what you just asked me to do.

    In my console outputs, from the LaunchWFActivity activity, I print out the value of the dependency property, and it is a valid GUID.

    From the ShutdownWFActivity activity, the value is Guid.Empty.

    It looks as though the binding isn't taking place, and I don't know how to fix it.


  • Drew Marsh

    I do know the type at design time.

    How does the workflow get hold of "workflowInstance2" if it was created in the first activity


  • St&amp;#233;phane Beauchemin

    databinding problem ...Just for testing, could you try binding the LaunchedWFGuid Property to Guid field in the workflow class and binding WFToShutDownGuidProperty to this workflow field

    If it doesn't work, stepping through the custom activities with the debugger can help...

    Serge



  • JFoushee

    Hi,

    thank you both, I will take a close look on that. But I think it will work for me.

    Cheers,
    Franz

  • Muzzzy

    Great ! In the meantime, I was writing a "emergency" scenario for you

     



  • AmitKGupta

    Hi kevin

    if wf1 is your State Machine WF and if wf2 is your Sequential WF:

    1.starting WF2 from WF1:

    -in an WF1 Custom activity, or from a Service:

    IStartWorkflow startWorkflow = executionContext.GetService(typeof(IStartWorkflow)) as IStartWorkflow;
    Guid instanceId = startWorkflow.StartWorkflow(this.TargetWorkflow, this.Parameters);

    -or use InvokeWorkflowActivity if you know the workflow type at design time.

    2.stopping WF2 from WF1

    you have to call workflowInstance2.Terminate()

    Serge



  • StateMachine invoke SequentialWorkflow