WF 从入门到精通workflow 运行时

WF 从入门到精通workflow 运行时

学习完本章后,你将掌握:

1.在你的应用程序中使用workflow

2.理解“WorkflowRuntime”对象的的基本功能

3.知道如何启动和停止workflow 运行时

4.能够使用各种workflow 运行时的相关事件

当 你在WF 环境中执行任务时,需要一些东西来监管执行的过程,这个东西就是命名为

WorkflowRuntime”的对象。 WorkflowRuntime 启动一个独立的工作流任务。在你的任务

执行过程中,WorkflowRuntime 也会针对不同的情况响应对应的事件。并 且,WorkflowRuntime

还能在你的执行环境中增加一个附加的服务来保持跟踪。

WF 架构纵览见下图:

WF 和你的应用程序并行执行。其实,我们需要你的应用程序作为宿主。宿主应用程序可

以是Windows Forms 应用程序,控制台应用程序,ASP.NET WEB 应用程序,甚至可以是一个

Windows ServerWF 运行时和你的应用程序同在一个.NET 应用程序域执行,每个应用程序域

只有一个唯一的WorkflowRuntime 实例,试图在一个 应用程序域中建立第二个

WorkflowRuntime 的实例的话,其结果就是抛出一个“InvalidOperationException”异常。

workflow 应用程序-workflows-意思指创建的逻辑上的一组活动。这些逻辑上的活

动用来完成你需要的工作流任务。当你宿主workflow 运行时的时 候,其实你就在操作工作

流中的活动并让workflow 运行时执行他们。其结果就是生成一个workflow 实例,workflow

实例是一个当前正执行 的workflow 任务,它能自己完成逻辑上的一组活动,回忆第一章吧,

活动能执行你提供的代码并且能对输入的数据做出相应的决定。下一章我们将简述工作流实

例,后面几章将对活动进行介绍。

在宿主应用程序中添加WF

一、创建一个名称为WorkflowHost 的控制台应用程序项目

二、为项目添加名为System.Workflow.Runtime 的引用

三、宿主workflow 运行时

1.打开Program.cs 文件准备编辑

2.在“using System.Text;”下添加以下代码:

using System.Workflow.Runtime

3.定位到“Main”方法,在里面添加以下代码:

WorkflowRuntime workflowRuntime=new WorkflowRuntime();

4.编译程序确认没有错误。在本章我们都将使用这一应用程序。

四、深入了解WorkflowRuntime 对象

我们现在已经在我们的宿主应用程序中建立了一个 WorkflowRuntime 类型的实例,该是

简单的了解怎样和这个对象交互的时候了。和大多数有用的对象一样,WorkflowRuntime

暴露了一些方法和属性,我们可用他们来控制Workflow 运行时的环境。表2-1 列出了所有

WorkflowRuntime 属性,表2-2 则列出了我们经常使用的方法。

2-1 WorkflowRuntime 的属性

属性 功能

IsStarted

用来指明workflow 运行时是否已经启动并准备接受workflow 实例。当宿主调用

StartRuntime”前IsStarted False。期间它一直维持True 直到宿主调用

StopRuntime”为止。需注意的是当它正在运行中你不能增加核心服务。

Name

获取或设置和WorkflowRuntime 关联的名字。Workflow 运行时正在运行中你不能

设置这个属性(也就是说当IsStarted True)。企图这样做的结果就是抛出一

个“InvalidOperationException”异常。

2-2 WorkflowRuntime 的方法

方法 功能

AddService

workflow 运行时添加指定的服务。能添加的服务类型和时间受到种种限

制。关于服务的详细信息将在第五章介绍。

CreateWorkflow

创建一个workflow 实例,它包含一些指定(但可选)的参数。假如workflow

运行时没有启动,该方法就调用StartRuntime 方法。

GetWorkflow

通过 指明workflow 实例的标识符(由一个Guid 组成)来检索workflow

例。假如这个workflow 实例是空闲和持久化保存的,它将被重新加载并执

行。

StartRuntime 启动workflow 运行时和相关服务,并引发“Started”事件。

StopRuntime 停止workflow 运行时和相关服务,并引发“Stoped”事件。

还有更多的关于WorkflowRuntime 的方法,但表2-2 中列出的方法是最经常用到的方法,

也是我们将重点关注的方法。在workflow 运行期间,WorkflowRuntime 也将在各种时间引发

许多事件,但我们将在后面的章节中介绍。

创建一个Workflow 运行时工厂

单 例和工厂设计模式的组合是强大的,因为工厂能保证只创建出一个曾创建的对象的单

一实例,这正好符合我们的要求(在这里使用单例模式的原因主要是从效率上考虑,其次一

个应用程序域也只能只有一个WorkflowRuntime),因为WorkflowRuntime 完全有可能在不

同的应用当中加载和启动(例 如独立的应用模块)。让我们看看怎样创建一个

WorkflowRuntime 工厂。

一、在项目中添加一个类型为类的新项,文件名为WorkflowFactory.cs

二、在WorkflowFactory.cs 源文件中添加如下的引用

using System.Workflow.Runtime;

三、在类中添加下面的代码:

//workflow runtime 的单一实例

private static WorkflowRuntime _workflowRuntime = null;

private static object _syncRoot = new object();

四、在上述代码后添加如下方法:

//工厂方法

public static WorkflowRuntime GetWorkflowRuntime()

{

//多线程环境下防止并发访问

lock (_syncRoot)

{

if (null == _workflowRuntime)

_workflowRuntime = new WorkflowRuntime();

}

return _workflowRuntime;

}

五、为类加上Public 关键字,为防止类被直接实例化,还必须为类加上static 标记,

如下所示:

public static class workflowFactory

启动workflow 运行时

参 考表2-2,里面有一个StartRuntime 方法,从我们的工厂对象中调用这个方法很有

意义,外部对象要求workflow 运行时对象无需处理或担心 运行时环境状态的初始化。我们

需要在我们的应用程序通过这一步来建立我们需要的workflow 环境。外部调用对象也需要

workflow 运行时对象易于 使用。

并不是一定要调用StartRuntime。假如我们建立了一个workflow 实例,StartRuntime

实际上就已被调 用。假如我们曾经创建了一个workflow 实例,或许并不用担心需要明确的

调用StartRuntime。但是,一旦我们添加服务时,明确地调用它就很有必要,因为可增强

代码的可维护性并确信运行时环境的状态已建立,这样任何人就都能使用workflow 运行时对

象。

因此让我们在我们的工厂对象中做些轻微的更改并直接调用StartRuntime

1.打开WorkflowFactory.cs 文件并定位到下面的代码上:

_workflowRuntime = new WorkflowRuntime();

2.在上面的代码下添加以下的代码:

_workflowRuntime.Starttime();

停止workflow 运行时

是 否有办法启动一个workflow 运行时很有意义,如何停止一个workflow 运行时也一样。

看看表2-2 吧,里面有一个StopRuntime 方法正 好符合我们要求。调用StopRuntime 方法会

卸载所有正执行的workflow 和服务并关闭workflow 运行时环境。当然,正确调用

StopRuntime 位置是在你申请停止逻辑结束之前或者应用程序域关闭前调用。

1.打开WorkflowFactory.cs 文件并定位到下面的代码上

_workflowRuntime = new WorkflowRuntime();

2.在上面代码的前面增加以下代码:

_workflowRuntime.Starttime();

3.WorkflowFactory.cs 中增加StopWorkflowRuntime 事件处理函数:

static void StopWorkflowRuntime(object sender, EventArgs e)

{

if (_workflowRuntime != null)

{

if (_workflowRuntime.IsStarted)

{

try

{

_workflowRuntime.StopRuntime();

}

catch (ObjectDisposedException)

{

}

}

}

}

以下是WorkflowFactory.cs 文件的完整源代码,在第五章之前我们不会做更多的改变:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Workflow.Runtime;

namespace WorkflowHost

{

public static class WorkflowFactory

{

//workflow runtime 的单一实例

private static WorkflowRuntime _workflowRuntime = null;

private static object _syncRoot = new object();

//工厂方法

public static WorkflowRuntime GetWorkflowRuntime()

{

//多线程环境下防止并发访问

lock (_syncRoot)

{

if (null == _workflowRuntime)

{

AppDomain.CurrentDomain.ProcessExit += new EventHandler(StopWorkflowRuntim

e);

AppDomain.CurrentDomain.DomainUnload += new EventHandler(StopWorkflowRunti

me);

_workflowRuntime = new WorkflowRuntime();

_workflowRuntime.StartRuntime();

}

}

return _workflowRuntime;

}

static void StopWorkflowRuntime(object sender, EventArgs e)

{

if (_workflowRuntime != null)

{

if (_workflowRuntime.IsStarted)

{

try

{

_workflowRuntime.StopRuntime();

}

catch (ObjectDisposedException)

{

}

}

}

}

}

}

现在我们有了一个workflow 运行时的创建工厂,然后我们将修改我们的主程序来使用

它。

使用workflow 运行时创建工厂

1.打开Program.cs 文件并定位到如下代码上:

WorkflowRuntime workflowRuntime=new WorkflowRuntime();

2.把上面的代码修改成以下代码:

WorkflowRuntime workflowRuntime=WorkflowFactory.GetWorkflowRuntime();

2-3 workflow 运行时的相关事件描述

事件 功能

Started workflow 运行时启动后激发。

Stopped workflow 运行时停止后激发。

WorkflowCompleted 当一个workflow 实例完成后激发。

WorkflowIdled

当一个workflow 实例进入空闲状态时激发。当

workflow 实例进入了空闲状态后,你就有机会把

他们从内存中卸载掉、存储到数据库并可在稍后

的时间把它们加载进内存。

WorkflowTerminated

当一个workflow 实例被终止后激发。在宿主中调

用一个workflow 实例的Terminate 方法、或通过

一个Terminate 活动、或当workflow 运行时产生

一个未经捕获的异常时都会终止该workflow

我们还将在第四章和第五章介绍更多的事件。

在我们为上面的事件添加相应的事件处理程序时,你会看到生成的代码和上一章我们创

建的基于工作台的顺序工作流应用程序中的代码完全一样(或几乎完全一样)。为了看看这

些事件的作用,我们需要停止应用程序主线程一段时间。因此,我们使用一个基于内核的自

动重置事件。一会儿后,我们将写出一些代码来使用上 述事件中的几个,你需要不时看看第

一章中PCodeFlow 项目中的Program.cs 文件,对比它们的不同以及该写入什么样的代码。尽

管它们并不完全 相同,但你在两个程序中还是能找到相同的内容。

处理workflow 运行时事件

1.启动Visual Studio,打开项目的Program.cs 源文件,定位到下面的代码上:

WorkflowRuntime workflowRuntiem=WorkflowFactory.GetWorkflowRuntime();

2.假如你用过.NET 的委托,下面的代码你将非常熟悉。我们需要为我们感兴趣的事件增

加相应的事件处理程序。我们现在就来为workflow 空闲时和完 成后增加相应的事件处理程

序。稍候我们还会增加我们所需要的更多的事件处理程序。记住,下面的代码在步骤1 定位

的代码的下面:

workflowRuntime.WorkflowIdled += new

EventHandler<WorkflowEventArgs>(workflowIdled);

3.下面的代码添加了对workflow 完成后的事件处理:

workflowRuntime.WorkflowCompleted += new

EventHandler<WorkflowCompletedEventArgs>(workflowCompleted);

4.现在添加对workflow 终止后的事件处理:

workflowRuntime.WorkflowTerminated += new

EventHandler<WorkflowTerminatedEventArgs>(workflowTerminated);

5.假如你编译并运行WorkflowHost(本项目),这个应用程序能通过编译并运行。但没

有执行workflow,因为我们并未告知 workflow 运行时去启动一个workflow 实例(我们将在

下章添加)。为以后做准备,我们还要添加一些代码。首先,为了激发workflow 中的 事件

(以便我们观察它们),我们需要停止主线程足够长的时间,因此我们还将添加自动重置事

件。在步骤34 的代码下添加以下代码。

Console.WriteLine("对待workflow 完成。");

waitHandle.WaitOne();

Console.WriteLine("完成.");

6.Main 方法前定义一个名为waitHandle 的静态成员:

private static AutoResetEvent waitHandle = new AutoResetEvent(false);

7.添加名称空间:

using System.Threading;

8.Vistual Studio 2008 创建的上面三个事件对应的事件处理程序内都包含“throw

new NotImplementedException();”。我们需要移除这些代码并定位到workflowIdled

的事件处理程序内,写入下面的代码:

Console.WriteLine("workflow 实例空闲中");

9.定位到workflowCompleted 的事件处理程序内,写入下面的代码:

Console.WriteLine("workflow 实例已完成");

waitHandle.Set();

10.定位到workflowTerminated 的事件处理程序内,写入下面的代码:

Console.WriteLine("workflow 实例已终止,原因:'{0}'",e.Exception.Message);

waitHandle.Set();

完整的代码见列表2-2

列表2-2 WorkflowHost 应用程序的完整代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Workflow.Runtime;

using System.Threading;

namespace WorkflowHost

{

class Program

{

private static AutoResetEvent waitHandle = new AutoResetEvent(false);

static void Main(string[] args)

{

WorkflowRuntime workflowRuntime = WorkflowFactory.GetWorkflowRuntime();

workflowRuntime.WorkflowIdled += new EventHandler<WorkflowEventArgs>(workflowRunti

me_WorkflowIdled);

workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(

workflowRuntime_WorkflowCompleted);

workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs

>(workflowRuntime_WorkflowTerminated);

Console.WriteLine("等待workflow 完成。");

waitHandle.WaitOne();

Console.WriteLine("完成.");

}

static void workflowRuntime_WorkflowIdled(object sender, WorkflowEventArgs e)

{

Console.WriteLine("workflow 实例空闲中");

}

static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArg

s e)

{

Console.WriteLine("workflow 实例已完成");

waitHandle.Set();

}

static void workflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventA

rgs e)

{

Console.WriteLine("workflow 实例已终止,原因:'{0}'",e.Exception.Message);

waitHandle.Set();

}

}

}

下一章我们将深入workflow 实例,假如现在你执行这个程序,他会一直挂起。为什么呢?

因为我们从未执行一个workflow 实例,因此我们加入的事 件的从未被激发,也就未执行对

应的事件处理程序。程序将永远挂起(或者你亲自终止它)。在下一章中当我们添加一个

workflow 实例并执行它时我们还会 看到这个程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章