狀態機工作流
在上一節Workflow筆記1——工作流介紹中,介紹的是流程圖工作流,后來微軟又推出了狀態機工作流,它比流程圖功能更加強大。
狀態機工作流:就是將工作流系統中的所有的工作節點都可以看做成一個狀態節點。每個節點都有N個狀態,其中都包含初始狀態、進入狀態、離開狀態等。當節點的狀態變化的時候會執行某個節點。
新建項目StatueWorkflowConsoleApp
自動添加了一個起始節點和一個狀態節點.
運行結果如下:
注意執行順序。接下來,擴展此工作流。
1、設置全局變量Num
2、雙擊T1,為變量Num賦值
new Random().Next(0,10)
運行結果如下:
啟動工作流
之前我們新建的工作流項目,都是通過如下方式來啟動工作流的。
Activity workflow1 = new Workflow1(); WorkflowInvoker.Invoke(workflow1);
而在工作中,我們通常不能通過這樣的方式來啟動工作流。因為我們的流程啟動后,我需要監控流程的各種狀態。而我們通過Invoke的方式啟動工作流,是無法監控工作流的狀態的。我們可以通過WorkflowApplication類啟動工作流。參考:https://msdn.microsoft.com/zh-cn/library/system.activities.workflowapplication(v=vs.110).aspx
WorkflowInvoker 包含同步調用工作流的實例方法和靜態方法。WorkflowInvoker 不允許實例控件,如保持、卸載或恢復書簽。
WorkflowApplication 類為單個工作流實例提供宿主。 它是由工作流運行時管理的實際工作流實例的代理。
- 創建新的工作流實例,或從實例存儲區中加載工作流實例。
- 提供擴展以供工作流實例內的活動使用。
- 控制工作流實例的執行。
- 恢復由工作流實例內的活動創建的書簽。
- 保留或卸載工作流實例。
- 接收工作流實例生命周期事件通知。
1、新建Windows窗體應用程序,WindowsWorkFlowApp
2、右鍵單擊項目WindowsWorkFlowApp,新建活動,添加狀態機
3、雙擊State1,添加輸入參數
4、再添加一個狀態和結束狀態
5、雙擊FinalState,在其中添加輸出
修改State2
6、修改“啟動工作流”按鈕的事件代碼如下:
private void btnStartWorkFlow_Click(object sender, EventArgs e) { WorkflowApplication app = new WorkflowApplication(new Activity1(), new Dictionary<string, object>() { {"InputName","神刀張三"} }); app.Run(); }
我們來看下WorkflowApplication的構造函數。
構造函數
名稱 |
說明 |
使用指定的工作流定義創建 WorkflowApplication 類的新實例。 |
|
創建 WorkflowApplication 類的新實例,該實例使用指定的工作流定義和參數值。 |
|
WorkflowApplication(Activity, IDictionary<String, Object>, WorkflowIdentity) |
創建的新實例 WorkflowApplication 類,該類使用指定的工作流定義和參數值和定義標識。 |
創建的新實例 WorkflowApplication 使用指定的工作流定義和定義標識的類。 |
7、由於我創建的是Windows應用程序,那么要想輸出控制台信息,我們必須修改項目的輸出方式
8、運行項目
WorkflowApplication生命周期
那么我們如何來監控工作流的狀態呢,我們可以使用指定的工作流定義構造 WorkflowApplication,處理所需的工作流生命周期事件,並通過調用 Run 來調用工作流。
在Run方法調用之前,我們來注冊生命周期事件,添加代碼如下:
#region 工作流生命周期事件 app.Unloaded = delegate(WorkflowApplicationEventArgs er) { Console.WriteLine("工作流 {0} 卸載.", er.InstanceId); }; app.Completed = delegate(WorkflowApplicationCompletedEventArgs er) { Console.WriteLine("工作流 {0} 完成.", er.InstanceId); }; app.Aborted = delegate(WorkflowApplicationAbortedEventArgs er) { Console.WriteLine("工作流 {0} 終止.", er.InstanceId); }; app.Idle = delegate(WorkflowApplicationIdleEventArgs er) { Console.WriteLine("工作流 {0} 空閑.", er.InstanceId); }; app.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs er) { Console.WriteLine("持久化"); return PersistableIdleAction.Unload; }; app.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs er) { Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}", er.InstanceId, er.UnhandledException.Message); return UnhandledExceptionAction.Terminate; }; #endregion
再次運行項目,結果如下:
多線程信號量機制
Run方法會開啟一個新的線程。而通常,我們需要等待工作流運行完成之后再回到主線程。那么我們可以使用AutoResetEvent,一個線程通過調用等待一個信號 WaitOne 上 AutoResetEvent。
在工作流實例化之前,就創建一個AutoResetEvent對象。
AutoResetEvent syncEvent = new AutoResetEvent(false);
然后在工作流的Completed事件中,執行Set方法,將事件狀態設置為有信號,從而允許一個或多個等待線程繼續執行,說白了就是一個喚醒操作。
syncEvent.Set();
最后在Run方法的后面,添加
syncEvent.WaitOne();
WaitOne方法將阻止當前線程,直到當前 WaitHandle 收到信號,從而實現等待工作流線程運行完成的功能。