Datasheet
Chapter 1: Workfl ow Programming Principles
23
foreach (Activity activity in this.EnabledActivities)
{
activity.Closed += Activity_Closed;
executionContext.ExecuteActivity(activity);
}
3. Finally, it returns ActivityExecutionStatus.Executing to inform the workflow run time that
ParallelActivity has not completed its execution yet because it is waiting for its child activities to
complete their execution. As mentioned earlier, a composite activity is not allowed to report the
completion of its execution unless every single one of its child activities is in either Initialized or
Closed state:
return ActivityExecutionStatus.Executing;
ParallelActivity scheduled all its child activities with the WF scheduler for execution in one shot. This
means that the WF scheduler now contains one work item for each child activity of ParallelActivity.
Each work item is basically a delegate that encapsulates a reference to the Execute method of the
respective child activity. Because the WF scheduler uses the FIFO algorithm to dispatch work items, the
child activities are executed in the order in which they were scheduled, which is basically the order in
which they were added to ParallelActivity.
The Execute method of each child activity may need to suspend the execution of the child activity
waiting indefinitely for external entities to deposit data into the appropriate workflow queues before the
child activity can resume its execution. When a child activity finally completes its execution, it raises its
Closed event, which in turn triggers the scheduling of the Activity_Closed event handler for execution.
This means that each child activity will end up adding a work item to the WF scheduler, where each
work item is a delegate that references the Activity_Closed event handler. In other words, the same
Activity_Closed event handler is invoked once for each child activity in the ParallelActivity activity.
When the WF scheduler invokes the Activity_Closed event handler, it passes an
ActivityExecutionContext object into it as its first argument. This object represents the execution context
of the event handler.
Let ’ s walk through the implementation of this event handler (refer to Listing 1 - 8 ). The event handler first
removes itself from the list of event handlers registered for the Closed event of the child activity that
triggered the invocation of the event handler:
e.Activity.Closed -= this.Activity_Closed;
Next, the event handler iterates through the child activities to check whether all child activities are in
either Initialized or Closed state. If even one child activity is not in one of these two states, the event
handler returns without reporting any change in the execution status of ParallelActivity. This means that
as far as the workflow run time is concerned, ParallelActivity is still in the Executing state because the
last time the workflow run time heard of a change in the execution status of ParallelActivity was when
the Execute method returned the ActivityExecutionStatus.Executing enumeration value:
foreach (Activity activity in this.EnabledActivities)
{
if (activity.ExecutionStatus != ActivityExecutionStatus.Initialized ||
activity.ExecutionStatus != ActivityExecutionStatus.Closed)
return;
}
c01.indd 23c01.indd 23 8/25/08 4:02:58 PM8/25/08 4:02:58 PM