July 2006 - Posts - Hendrik Swanepoel

Hendrik Swanepoel

July 2006 - Posts

Execute a child activity and wait for the results

I came into a situation where I had to selectively execute a child activity. I wanted the activity to execute it's first child, wait for the results and then based on those results execute the next child.

The reason for this was that I wanted to write an Ifelse activity which takes activities as conditions (Instead of making my business user write code for code conditions) and based on the conditions results execute the rest of the branch.

I'll upload the complete IfElseActivity ASAP.

Step 1:

In order to execute a child activity, the parent activity has to implement the IActivityEventListener<ActivityExecutionStatusChangedEventArgs> interface. This enables it to subscribe to execution events executed in contexts spawned by the parent. This post gives some insight on contexts: http://blogs.msdn.com/advancedworkflow/archive/2006/03/21/557121.aspx

Step 2:

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
//Spawn the context (Execution sphere for your child activity)
ActivityExecutionContext context = executionContext.ExecutionContextManager.CreateExecutionContext(EnabledActivities[theChildIndex]);
//Register to get an event on this activity if the child activity's status is set to closed
context.Activity.RegisterForStatusChange(ClosedEvent, this);
//Execute the root activity of the context
context.ExecuteActivity(context.Activity);
return ActivityExecutionStatus.Executing; //Important to return Executing because the child will only execute after this method has finished
}

You can only spawn an ActivityExecutionContext for direct children on the container activity.

Step 3:

In the OnEvent method which was implemented from the IActivityEventListener interface, we do the following:

       void IActivityEventListener<ActivityExecutionStatusChangedEventArgs>.OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e)
        {
            
if (null == sender)
                
throw new ArgumentNullException("sender");
            
if (null == e)
                
throw new ArgumentException("e");

            
//This cis the spawned context with the child activity as the root
            
ActivityExecutionContext context = sender as ActivityExecutionContext;

            
if (null == context)
                
throw new ArgumentException("The sender must be an ActivityExecutionContext", "sender");

            
//This event handler will be triggered for every subscribed status change
            
if (e.ExecutionStatus == ActivityExecutionStatus.Closed)
            {
                
//get a reference to the root activity of the context (Your child activity)
                
MyActivity myActivity = e.Activity as myActivity;
                
//Do whatever you want to do with the activity - something more meaningful as this :)
                
if (myActivity.Bla == "Blie")
                {
                    Console.WriteLine("Bla was Blie");
                }

                
//Ensure that this activity finishes executing and that the child activity is closed
                
e.Activity.UnregisterForStatusChange(ClosedEvent, this);
                ActivityExecutionContextManager manager = context.ExecutionContextManager;
                manager.CompleteExecutionContext(manager.GetExecutionContext(e.Activity));
                context.CloseActivity();
            }
        }

Reasons to do this would be to execute a child activity more than once, or as in my scenarrio to provide an ifelse branch with activities as the condition.

powered by IMHO 1.3

Custom Windows Workflow Foundation IfElseActivity

My requirement for an IfElseActivity was for non coders to use it. Normally an IfElse activity will work based on a Code condition which is specified with code on the workflow.

We allow for business users to manage subsets of systems using an embedded workflow editor we provide for their use. Obviously we can't tell our business user to "just learn some simple csharp".. I wanted to have an IfElseActivity where you can use activities with "return values" as checks on the IfElse branch, meaning the user will drag on an IfElse activity and on the one branch drag on other special activities which will determine whether the branch should be executed.

I ended up writing an IfElseActivity that looks like this:

Each branch contains two activities, a condition preview activity and an execution block activity. To implement a new check, implement from the IConditionActivity in the project which exposes an Evaluation property and a Negated property.

The IfElseActivity will execute your check and then decide whether it will continue to the next check based on the Evaluation property you implemented. All the checks associated with the branch's condition preview needs to pass before the branch will execute. You can also negate the check, meaning the check needs to return false in order for it to pass.

You can then proceed in dragging the activities you want to execute in the branch onto the Execution activity. I did this for branch 1 with a code activity. If the first branch does not pass, it will proceed to the next branch. You can also have more than two branches.

Download the solution and have a look: http://novarank.com/customifelse.zip

[Update:] You need to install netfx3 and the latest version of vs.net extensions for windows workflow.