Couple of custom activities that you can use to synchronize branches of a ParallelActivity
You could use a SynchronizationScopeActivity, but this would block execution all together in the other branches since the thread is locked until the activity is done executing. If that is not the behavior you are looking for here are two options. First, WaitFor, will block the branch that it is in until a selected activity in another branch is Closed or Executing. With this activity in the execute method you find out the execution status for the activity you are waiting for and if it is not status you subscribe for the StatusChanged event. Once the activity changes to the correct status the WaitFor is closed and the next child in that branch will execute.
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
ActivityExecutionStatus status;
Activity activity = GetExecutableActivity(this.Activity);
switch (activity.ExecutionStatus)
{
case ActivityExecutionStatus.Executing:
if (this.Status == "Closed")
{
activity.StatusChanged += this.OnStatusChangeHandler;
status = ActivityExecutionStatus.Executing;
}
else
{
status = ActivityExecutionStatus.Closed;
}
break;
case ActivityExecutionStatus.Closed:
status = ActivityExecutionStatus.Closed;
break;
default:
activity.StatusChanged += this.OnStatusChangeHandler;
status = ActivityExecutionStatus.Executing;
break;
}
return status;
}
The other, SynchronizeActivity, you put one or more, must be equal, in each branch. When the activity executes is checks the other synchronize activities at the same level to see what there status is. If they are executing it ignores them and if they are initialized it will subscribe for the Executing event on that sybling. Once they are all executing then they are all closed allowing the next child in each branch to execute.
private ActivityExecutionStatus SubscribeSibling(ActivityExecutionContext context)
{
this.Properties.Clear();
ActivityExecutionStatus childStatus;
bool closed = false;
int count = 0;
int index = 0;
CompositeActivity parent = this.Parent;
// First find out if there are more than one syncronize in each branch
// and if so which one this one is.
foreach (Activity child in parent.Activities)
{
if (child is Synchronize)
{
if (child == this)
{
index = count;
}
++count;
}
}
foreach (CompositeActivity sequence in parent.Parent.EnabledActivities)
{
if (sequence != parent)
{
count = 0;
foreach (Activity child in sequence.EnabledActivities)
{
if (child is Synchronize)
{
if (count == index)
{
childStatus = child.ExecutionStatus;
switch (childStatus)
{
case ActivityExecutionStatus.Executing:
break;
case ActivityExecutionStatus.Closed:
closed = true;
break;
default:
this.Properties.Add(child.Name, child.Name);
child.Executing += this.OnStatusChangeHandler;
break;
}
break;
}
else
{
++count;
}
}
}
}
}
if (this.Properties.Count == 0)
{
return ActivityExecutionStatus.Closed;
}
else
{
if (closed)
{
throw new Exception("One of the syblings is already closed but there are '" + this.Properties.Count + "' syblings that are still being waited on.");
}
else
{
return ActivityExecutionStatus.Executing;
}
}
}
This posting is provided "AS IS" with no warranties, and confers no rights.
Comments
- Anonymous
September 12, 2007
You might think that the ParallelActivity in Windows Workflow Foundation is misnamed. At the very least,