- 理解AEC(ActivityExecutionContext)
- childActivity(1) or childActivity(2) 相互有影响么?
- childActivity(2)的父Activity是谁?
- 分析SequenceActivityandConditionedActivityGroup
- 自定义一个Rollback的Activity
- 创建了一个NavigateRequest类,用以存储源activity和目标activity,
- 然后把他用外部服务传入workflowRuntime的WorkflowQueueingService里,
- 然后在Excute()检查NavigateRequest是否存在,如果存在,将会停掉现在执行的Activity,将调度到目标Activity里。可以通过ConditionedActivityGroup去了解Activity执行的过程
当Workflow runtime执行一个Activity时,他会为这个Activity新建一个ActivityExecutionContext,它包含了执行Activity信息。更重要的一点是AEC是根据Activity临时变化的并且这个Activity是深copy,所以就很难得到执行这个Activity之前得AEC和Activity实例。当一个Activity执行多次的时候,他必须被copy多次,同时AEC也创建一个新的,代码:
ActivityExecutionContextchildContext=currentContext.ExecutionContextManager.CreateExecutionContext(childActivity);
它将会根据父AEC去为ChildActivity创建一个新的AEC,以维护自己。假设我们有一个自定义的Activity叫WorkflowRoot,我们去copy它的子Activity,会有以下结果:
RootContext
| WorkflowRoot (1)
| childActivity (1)
| grandChildActivity (1)
- childContext
childActivity (2)
grandChildActivity (2)
有2个问题:
一旦Clone了这个实例,这2个实例就 没有联系了。
WorkflowRoot (1),所以新clone的Activity的父activity任然执行原Activity
SequenceActivity将一个一个执行它的子activity,执行完最后一个Activity后这个SequenceActivity将会关闭。
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
if (executionContext == null)
{
throw new ArgumentNullException("executionContext");
}
if (base.EnabledActivities.Count == 0)
{
this.OnSequenceComplete(executionContext);
return ActivityExecutionStatus.Closed;
}
base.EnabledActivities[0].RegisterForStatusChange(Activity.ClosedEvent, this); //①
executionContext.ExecuteActivity(base.EnabledActivities[0]); //②
base.SetValue(ActiveChildQualifiedNameProperty, base.EnabledActivities[0].QualifiedName);
return ActivityExecutionStatus.Executing;
}
①注册了一个事件,当第一个Activity执行完毕后,将会触发OnEvent方法。②告诉我们要手工执行这个Activity
void IActivityEventListener<ActivityExecutionStatusChangedEventArgs>.OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e)
{
if (sender == null)
{
throw new ArgumentNullException("sender");
}
if (e == null)
{
throw new ArgumentNullException("e");
}
ActivityExecutionContext executionContext = sender as ActivityExecutionContext;
if (executionContext == null)
{
throw new ArgumentException(SR.Error_SenderMustBeActivityExecutionContext, "sender");
}
e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this);
SequenceActivity activity = executionContext.Activity as SequenceActivity;
if (activity == null)
{
throw new ArgumentException("sender");
}
if ((activity.ExecutionStatus == ActivityExecutionStatus.Canceling) || ((activity.ExecutionStatus == ActivityExecutionStatus.Faulting) && ((bool) base.GetValue(SequenceFaultingProperty))))
{
if (activity.ExecutionStatus == ActivityExecutionStatus.Faulting)
{
base.RemoveProperty(SequenceFaultingProperty);
}
base.RemoveProperty(ActiveChildQualifiedNameProperty);
executionContext.CloseActivity();
}
else if ((activity.ExecutionStatus == ActivityExecutionStatus.Executing) && !this.TryScheduleNextChild(executionContext))
{
this.OnSequenceComplete(executionContext);
executionContext.CloseActivity();
}
}
this.TryScheduleNextChild(executionContext)将执行下一个Activity
然而ConditionedActivityGroup就较为复杂。它的子节点可能被执行多次,所以当子节点的状态为pending/executing/idle时,它将维护一个状态集合,当他要执行或重新执行这个Activity时,执行以下方法:
private void ExecuteChild(ConditionedActivityGroup cag, Activity childActivity, ActivityExecutionContext context)
{
ActivityExecutionContext context2 = GetChildExecutionContext(context, childActivity, true);
cag.CAGState.ChildrenStats[childActivity.QualifiedName].State = CAGChildState.Excuting;
context2.Activity.RegisterForStatusChange(Activity.ClosedEvent, this);
context2.ExecuteActivity(context2.Activity);
}
我们可以通过分析系统中的Activity去学习自己定义Activity
自定义了一个NavigatorActivity,他的功能就是可以rollback或forward到一个Activity,当我从一个Activity到另一个activity,
整个的架构
定义NavigateRequest类:
public string SourceActivity
{
get { return this.source; }
set { this.source = value; }
}
public string TargetActivity
{
get { return this.target; }
set { this.target = value; }
}
public string ResponsibleActivity
{
get { return this.responser; }
set { this.responser = value; }
}
public NavigateDirection? Direction
{
get { return this.direction; }
set { this.direction = value; }
}
public string Remark
{
get { return this.remark; }
set { this.remark = value; }
}
public NavigateRequest(string source, string target, string remark)
{
if (String.IsNullOrEmpty(source))
{
throw new ArgumentNullException("source");
}
if (String.IsNullOrEmpty(target))
{
throw new ArgumentNullException("target");
}
if (source == target)
{
throw new ArgumentException("Cannot navigate to itself.");
}
this.source = source;
this.target = target;
this.remark = remark;
}
public NavigateRequest(string source, string target)
: this(source, target, "")
{
}
public NavigateRequest(NavigateDirection direction, string source, string target)
: this(source, target)
{
this.direction = direction;
}
public NavigateRequest(NavigateDirection direction, string source, string target, string responser)
: this(direction, source, target)
{
this.responser = responser;
}
}
/// <summary>
/// The direction of navigate, rollback is backward navigation, while jump is forward.
/// </summary>
public enum NavigateDirection
{
Backward, Forward
}
注册rollbackactivity