locked
Can you programmatically "execute" a FlowDecision activity? RRS feed

  • Question

  • Is it possible to manually execute (in code) a FlowDecision activity in a workflow based on it's condition? 

    We have a scenario where we are walking through a Workflow one activity at a time, using the FlowNode.Next concept.  When we get to a FlowDecision, things break down a bit because it's a decision point and there's no obvious "Next" node ... so we essentially need to evaulate the condition on the fly and then choose to schedule either the True activity or the False one.

    Any thoughts?

    Wednesday, August 4, 2010 5:31 PM

Answers

  • Ah, the way to get the result here is not to access the outargument, but to use the correct scheduling overload from NativeActivityContext... one that takes a CompletionCallback<T> where the result will be available to the callback as a parameter.

    http://msdn.microsoft.com/en-us/library/dd986772.aspx

    Tim
    • Marked as answer by Kofoed Monday, August 9, 2010 9:40 PM
    Monday, August 9, 2010 5:06 PM

All replies

  • No- FlowDecision is not an Activity, so it can't be run outside a Flowchart activity.
    Wednesday, August 4, 2010 6:15 PM
  • The FlowDecision activity I'm talking about is inside a Flowchart.  I'm moving through a Flowchart via the FlowNodes collection and the NEXT property on each FlowNode.

    Wednesday, August 4, 2010 8:14 PM
  • Would developing the logic outside the flowchart work? I'm not clear on your implementation, but would a Pick or Switch activity work for your scenario?
    Wednesday, August 4, 2010 9:36 PM
  • I don't believe so.

    The scenario is essentially that we are creating an app that rehosts the Workflow designer.  Users can create their own workflows using FlowDecision and other activities - we've defined it so that they're basically just working within the realm of a Flowchart, nothing else.  So users drag on activities into the Flowchart.

    We have a tool that allows users to "walk through" a workflow they've defined in a host runtime.  They can click next and previous buttons to essentially move through a workflow one activity at a time.  So the issue is, when they come to a FlowDecision, something has to be done behind the scenes as the FlowDecision has no UI associated with it of course.  We want to just evaulate the condition on the fly and then move to the next UI activity in the Flowchart workflow based on the TRUE or FALSE result.

    Is that remotely possible?  I imagine there might be something u could do with the VB expression of the condition, but I don't really know where to start.

    Wednesday, August 4, 2010 10:36 PM
  • So I'm assuming this isn't really plausible?

    Thursday, August 5, 2010 6:27 PM
  • Do you want to be running the workflow for real or just simulating it?
    In general I don't know how you will simulate conditions accurately without executing your workflow, although for simulation you could let your user choose whether the condition is true or not...
    Have you seen the Workflow Simulator (Visual Workflow Tracking) sample already? (http://blogs.msdn.com/b/kushals/archive/2009/12/29/visualworkflowtrackingwithstepservice.aspx)
    Tim

    Thursday, August 5, 2010 8:29 PM
  • Yes, we are running the workflow for real.  Each activity is scheduled and run in a sequential manner (even though it's a Flowchart).  So when we get to a FlowDecision point in the workflow, the condition needs to be "run" and the proper activity scheduled.

    Here's a code snippet for the method that currently does the scheduling of next activities to run in the workflow:

        private void ScheduleNextActivity(NativeActivityContext executionContext, ActivityInstance completedAtivityInstance)
        {
          System.Activities.Activity activityToBeScheduled = null;
    
          if (completedAtivityInstance == null) //No completed Activity
          {
            FlowStep step = this.StartNode as FlowStep;
            activityToBeScheduled = step.Action;
          }
          else
          {
            //Schedule Next of Completed Activity
            foreach (FlowNode node in this.Nodes)
            {
              FlowStep step = node as FlowStep;
    
              if (step != null && step.Action.Id == completedAtivityInstance.Activity.Id)
              {
                _mPreviousNode = node;
    
                FlowNode nextNode = step.Next;
    
                // TODO - what do we do here if we hit a FlowDecision node? We need to somehow evaluate
                //    the condition (if possible?) and then choose to schedule the activity in either
                //    the TRUE or the FALSE branch. The question is how to evaulate the condition because
                //    at this point the Result is null.
                if (nextNode is FlowDecision)
                {
                  FlowDecision flowNode = (FlowDecision)nextNode;
                  Activity<bool> decision = flowNode.Condition;
                  OutArgument<bool> result = decision.Result;
    
                  //activityToBeScheduled = nextNode;
                }
    
                if (nextNode != null)
                {
                  FlowStep nextStep = nextNode as FlowStep;
                  activityToBeScheduled = nextStep.Action;
                }
                break;
              }
            }
          }
    
          if (activityToBeScheduled != null)
          {
            executionContext.ScheduleActivity(activityToBeScheduled, this.onChildComplete);
          }
        }
    
    Thursday, August 5, 2010 9:51 PM
  • The conditions on the flowswitch and flowdecision are expressions, which are workflow activities, the way flowchart deals with this is schedule the expression for execution, then use the result. I'm still not sure if I figured out what you are doing, but maybe you can do the same thing?

    Tim
    Sunday, August 8, 2010 7:01 PM
  • Yep, I think u got it ... I found in the meantime that's what I need to do - schedule the expression for execution.  So that gets me past the main issue, and I can get a result - however I'm trying to evaluate the result and I'm getting a runtime exception:

    An Activity can only get the location of arguments which it owns. Activity 'Flowchart' is trying to get the location of argument 'Result' which is owned by activity 'VisualBasicValue<Boolean>'.

    The error occurs in the "Try" clause in the code below.  The code is basically what we do when we come to a FlowDecision node and have already executed the expression.

              else if (node is FlowDecision)
              {
                FlowDecision flowNode = (FlowDecision)node;
    
                Activity<bool> decision = flowNode.Condition;
    
                if (decision != null && decision.Id == completedActivityInstance.Activity.Id)
                {
                  _mPreviousNode = node;
    
                  Microsoft.VisualBasic.Activities.VisualBasicValue<bool> vb = decision as Microsoft.VisualBasic.Activities.VisualBasicValue<bool>;
                  OutArgument<bool> outArgResult = decision.Result;
    
                  bool result = true;
                  
                  try
                  {
                    result = executionContext.GetValue<bool>(decision.Result); 
                  }
                  catch
                  {
                    //TODO: how do we get around this error? Once we do, this implementation will be complete
                    //An Activity can only get the location of arguments which it owns. Activity 'Flowchart' is trying to get the location of argument 'Result' which is owned by activity 'VisualBasicValue<Boolean>'.
                  }                          
    
                  if (result)
                  {
                    FlowStep trueStep = flowNode.True as FlowStep;
    
                    if (trueStep != null && trueStep.Action != null)
                      activityToBeScheduled = trueStep.Action;
                  }
                  else
                  {
                    FlowStep falseStep = flowNode.False as FlowStep;
    
                    if (falseStep != null && falseStep.Action != null)
                      activityToBeScheduled = falseStep.Action;
                  }
                }
    
    Monday, August 9, 2010 3:46 PM
  • Ah, the way to get the result here is not to access the outargument, but to use the correct scheduling overload from NativeActivityContext... one that takes a CompletionCallback<T> where the result will be available to the callback as a parameter.

    http://msdn.microsoft.com/en-us/library/dd986772.aspx

    Tim
    • Marked as answer by Kofoed Monday, August 9, 2010 9:40 PM
    Monday, August 9, 2010 5:06 PM
  • Ahhhh .... bingo.  Thanks!
    Monday, August 9, 2010 9:40 PM