Michael's

focus on architecture & hi-performance

WF持久化服务

WF运行时引擎提供了一系列的底层函数库,用以执行和管理工作流生存周期。该运行时引擎架构是高度可扩展的。例如,该运行时架构可以宿主在任何类型的Windows进程中,而不是指定类型的宿主。而且更重要的是,运行时引擎的大多数功能,以单独的运行时“服务”形式实现,很容易定制。(Mic:可以通过WorkflowRuntime.AddService方法来添加相应的服务)实际上,开发人员能很容易地添加/删除各种服务到运行时引擎;而且通过使用WF库,开发人员能创建自己的各种运行时服务。

基本WF服务

Service

Function

Persistence

Save and restore the state of the workflow at certain points to-from a durable medium

Tracking

Tracking services are designed to monitor workflow execution through the exchange of data that can then be persisted to a storage medium or output on a specified stream, the System. Console for instance

Timer

The Timer service within the Windows Workflow Foundation (WF) runtime engine is responsible for managing time-outs such as those required by the Delay activity

Transactions

Provides the transaction support needed for data integrity.

Threading

Dispense physical threads used to execute workflow instances

默认情况下,工作流宿主程序在内存中执行工作流实例(workflow instances),没有任何状态的维护工作。然后在很多场景下,例如说一个长期运行的流程(BPM,我在上篇post中提及过),就需要一种机制在执行的某一点可以持久化工作流状态。按照WF的术语来说,持久化工作流到持久化媒介被称作dehydration。

在WF中,持久化通过使用一个运行时服务,该服务的主要功能是保存/复原工作流某一点的状态到/从一个持久化媒介。WF提供了一个默认的持久化服务:SQLStatePersistenceService(Mic:估计一般人都不会去用它J),然而通过可扩展的运行时服务模型,开发人员可以选择性地创建自己的持久化服务。下面就对这进行解释:

下面是一个顺序工作流demo,分为三个活动:

Activity

Activity Type

Function

Before Serialize

Code

Prints the phrase “Before Serialize” to the console

Delay1

Delay

Suspends the workflow execution for a period of 50 seconds

After Serialize

Code

Prints the phrase “After Serialize” to the console

现在来配置持久化服务:

1.创建和配置持久化数据库

2.添加SQLStatePersistanceService实例对象到WorkFlow运行时中(我刚才已经说过用法)

3.保存工作流实例状态。

第一点就不描述了,第二点简单提一下,主要有两种方式,第一种我已经在前面说过,第二种是在配置文件中加入:

<WorkflowRuntime Name="SampleApplication" UnloadOnIdle="true">

<Services>

<add type="System.Workflow.Runtime.Hosting.SqlStatePersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ConnectionString="Data Source=localhost;Initial Catalog=WFState;Integrated Security=True;" />

</Services>

</WorkflowRuntime>

一旦该持久化服务添加到工作流运行时引擎之后,它就开始逐步将工作流实例状态持久化到持久化媒介了。有两种方法:

1. 强制工作流实例持久化:调用该工作流实例的Unload方法。默认情况下,该方法使用与之关联的持久化服务,会讲工作流实例从内存中移除,然后保存其状态。

2. 另一种方法,是让工作流运行时进入一个idle状态时持久化实例状态。但是,这样必须要设置UnLoadOnIdle属性为true。而且该设置必须在StartRuntime方法调用之前进行。差不多像这样:

workflowRuntime.UnloadOnIdle = true;

workflowRuntime.StartRuntime();

工作流运行时是通过调用持久化服务的SaveWorkflowInstanceState方法来实现的。这是一个虚方法,同时,StatePersistenceService是所有持久化服务类的基类。

从持久化媒介中恢复持久化数据

WF运行时引擎能够复原工作流实例到内存中,以允许继续按计划执行。一种方法是通过调用工作流实例的Load方法。运行时引擎也可以在达到一个idle时刻复原一个工作流实例。

另一种方法是显式地与持久化服务交互。这样就必须调用WorkflowRuntime类的GetWorkflow和Loads方法。

假设一种场景:在到达一个idle状态时,我们告诉工作流运行时持久化工作流实例的状态,然后就在它刚刚达到After_Serialize代码活动时马上挂起流的执行。这个时候,我们可以查询数据库中的InstanceState表获取序列化的状态。

SELECT uidInstanceID, state

FROM InstanceState

If we then restore the instance using the code below we will ge the following output, “After Serialize…”.

workflowRuntime = new WorkflowRuntime();

workflowRuntime.AddService(new SqlStatePersistenceService("Data Source=localhost;Initial Catalog=WFState;Integrated Security=True");

workflowRuntime.AddService(new SqlTimerService("Data Source=localhost;Initial Catalog=WFState;Integrated Security=True"));

workflowRuntime.StartRuntime();

CurrentInstance = workflowRuntime.GetWorkflow(new Guid("DC466C9E-5285-4D88-A9A2-FB79EAF81360"));

CurrentInstance.Load();

开发自定义持久化服务

   1:      public class FilePersistenceProvider: StatePersistenceService
   2:      {
   3:          public FilePersistenceProvider(string basedir)
   4:          {
   5:              FBaseDir = basedir;
   6:          }
   7:          
   8:          private string FBaseDir;
   9:          public override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock)
  10:          {
  11:              ActivityExecutionContextInfo contextInfo = (ActivityExecutionContextInfo)rootActivity.GetValue(Activity.ActivityExecutionContextInfoProperty);
  12:              SerializeActivity(rootActivity, contextInfo.ContextGuid);
  13:          }
  14:          
  15:          // load workflow instance state
  16:          public override Activity LoadWorkflowInstanceState(Guid instanceId)
  17:          {
  18:              object obj = DeserializeActivity(null, instanceId);
  19:              return (Activity)obj ;
  20:          }
  21:          // unlock workflow instance state. 
  22:          // instance state locking is necessary when multiple runtimes share instance persistence store
  23:          public override void UnlockWorkflowInstanceState(Activity state)
  24:          {
  25:              //not implemented...
  26:          }
  27:          
  28:          // save completed scope activity state
  29:          public override void SaveCompletedContextActivity(Activity rootActivity)
  30:          {
  31:              ActivityExecutionContextInfo contextInfo = (ActivityExecutionContextInfo)rootActivity.GetValue(Activity.ActivityExecutionContextInfoProperty);
  32:              SerializeActivity(rootActivity, contextInfo.ContextGuid);
  33:          }
  34:          
  35:          // Load completed scope activity state.
  36:          public override Activity LoadCompletedContextActivity(Guid activityId, Activity outerActivity)
  37:          {
  38:              object obj = DeserializeActivity(outerActivity, activityId);
  39:              return (Activity)obj ;
  40:          }
  41:          
  42:          private void SerializeActivity(Activity RootActivity, Guid id)
  43:          {
  44:              string filename = FBaseDir + "\\" + id.ToString() + ".bin";
  45:              FileStream stream = new FileStream(filename, FileMode.OpenOrCreate);
  46:              RootActivity.Save(stream);
  47:              stream.Close();
  48:          }
  49:          
  50:          private object DeserializeActivity(Activity RootActivity, Guid id)
  51:          {
  52:              string filename = FBaseDir + "\\" + id.ToString() + ".bin";
  53:              FileStream stream = new FileStream(filename, FileMode.Open);
  54:              object Result = Activity.Load(stream, RootActivity);
  55:              return Result;
  56:          }
  57:      }

要强调一下的是:

StatePersistenceService 是所有持久化工作流服务的基类,自定义服务类从它继承后,通过override一些相应的方法,就可以调用自定义的持久化方法。

后记:

工作流运行时默认是在Unload时才持久化工作流实例的,而在设置UnloadOnIdle属性为true之后,从这个属性的字面意思也可以看出,只要在Idel的时候,Unload就会触发了,也就是说此时会进行持久化的操作,这是由工作流运行时引擎自动执行的,但是我们也可以通过调用我们自定义的持久化服务的Save方法来将当前的工作流实例持久化。

原文链接: http://weblogs.asp.net/gsusx/archive/2005/10/05/426699.aspx

posted on 2007-02-09 08:37 m.s 阅读(2411) 评论(4) 编辑 收藏

导航

统计信息

News