技术开发 频道

探秘WF4 Beta2中工作流对象模型

       3 深入分析Activity执行的流程

  一个Activity实例到底是如何执行的?一切得从WorkItem类开始。

  WorkItem是一个抽象基类,提供了几个抽象方法,其中最重要的就是Execute()方法:

internal abstract class WorkItem

{

    
//……

    
private ActivityInstance activityInstance;

    
public abstract bool Execute(ActivityExecutor executor,

        BookmarkManager bookmarkManager);

}

 

        上述声明中还有两个很重要的类ActivityInstance和ActivityExecutor。

  ActivityInstance代表着正在运行的一个Activity实例,它包容一堆的internal方法可以完成Activity的执行(Execute)取消(Cancel)和放弃(Abort)的功能。 ActivityExecutor则负责调用ActivityInstance中的这些方法。

  WorkItem有一堆的子类,这些子类又派生出“孙”类。比如,其中的一个分支如下:

图2 WorkItem 类派生

  不管有几个子孙,后代一般都重写了WorkItem所定义的Execute()抽象方法。

  我们以ExecuteRootWorkItem类为例,顾名思义,这应该是与工作流中最顶层的Activity相对应的WorkItem。它的Execute()方法如下所示:

public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)

{

    
return base.ExecuteBody(executor, bookmarkManager, this.resultLocation);

}

 

       它将调用基类ExecuteActivityWorkItem的ExecuteBody()方法,此方法的关键代码如下:

protected bool ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

{

      
//……

        
base.ActivityInstance.Execute(executor, bookmarkManager);

    
//……

}

       可以看到,它直接跳去执行最顶层基类WorkItem所定义的ActivityInstance对象的Execute()方法。此方法的代码如下:

internal void Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)

{

    
//……

    
this.Activity.InternalExecute(this, executor, bookmarkManager);

}

       注意ActivityInstance实际上封装了一个Activity对象:

public sealed class ActivityInstance : ActivityInstanceMap.IActivityReference

    {

              
public Activity Activity { get; internal set; }

            
//……

    }

       所以,ActivityInstance对象的Execute()方法实际上执行的是Activity对象的InternalExecute()方法。再追踪下去:

internal virtual void InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)

{

    
//……

        executor.ScheduleActivity(
this.runtimeImplementation, instance, null, null, null);

   }

        注意:上述代码是Acitivity对InternalExecute()默认的实现方式,它的子类(比如CodeActivity)通常会重写它。

  可以看到,在ActivityInstance对象的Execute()方法中,执行流程转给了从前面一路传送过来的ActivityExecutor对象,由此对象的ScheduleActivity方法负责将Activity插入到工作项队列中。

  ActivityExecutor.ScheduleActivity方法又进行了一个“倒手”,调用自己的ScheduleBody()方法:

private ActivityInstance ScheduleActivity(……)

{



    
//……

    
this.ScheduleBody(scheduledInstance, requiresSymbolResolution, argumentValueOverrides, resultLocation);

}

 

        在ScheduleBody()方法中,“佛祖”终于现出真身,我们看到了Scheduler的身影:

internal void ScheduleBody(ActivityInstance activityInstance, bool requiresSymbolResolution, IDictionary<string, object> argumentValueOverrides, Location resultLocation)

{

    
if (resultLocation == null)

    {

      
//……

        
this.scheduler.PushWork(new ExecuteExpressionWorkItem(activityInstance, requiresSymbolResolution, argumentValueOverrides, resultLocation));

//……

}

        在上述代码中,Scheduler对象将activityInstance转换为了一个ExecuteExpressionWorkItem,然后将其插入到工作项队列中等待执行。

  现在我们看到,默认情况下,对ExecuteRootWorkItem的执行将导致一个新的ExecuteExpressionWorkItem工作项被插入到工作项队列中。

0