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 實例並執行它時我們還會 看到這個程序。

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