一、WorkFlow介紹
1. WorkFlow是OA系統中必不可少的模塊,並且在以后的大多數的工作中,都會用到工作流模式的開發。關於這方面的開發,我第一次接觸到的是關於釘釘里的氚雲功能,感覺還是做的相當不錯,用戶只需要拖動控件,然后配置數據庫,就會形成對應的工作流,並不需要大量的代碼編寫。
二、創建一個demo案例:
1. 這兒創建的是一個控制台程序demo。
主程序代碼如下:
using System; using System.Linq; using System.Activities; //主要的 using System.Activities.Statements; namespace WorkflowConsoleApplication1 { class Program { static void Main(string[] args) { //new了一個工作流類 Activity workflow1 = new Workflow1(); //啟動工作流 WorkflowInvoker.Invoke(workflow1); Console.ReadLine(); } } }
其中需要注意的是inputCodeActivity1,該控件是一個代碼活動,就是指此處需要一些別的操作,具體創建如下:
並且編輯如下代碼,提供一個返回參數:
public sealed class inputCodeActivity1 : CodeActivity { // 定義一個字符串類型的活動輸入參數 //public InArgument<string> Text { get; set; } //輸出參數 public OutArgument<int> returnMoney { get; set; } // 如果活動返回值,則從 CodeActivity<TResult> // 派生並從 Execute 方法返回該值。 protected override void Execute(CodeActivityContext context) { // 獲取 Text 輸入參數的運行時值 //string text = context.GetValue(this.Text); int m; string money = Console.ReadLine(); int.TryParse(money, out m); //為輸出參數設置參數 context.SetValue(returnMoney,m); } }
最終全部創建好,之后,如下:
最終的運行結果如下:
備注:4.0版本的沒有狀態機工作流,需要切換到別的版本才有
三、 WorkflowApplication啟用工作流以及傳參,與常用觸發事件。
1. WorkflowApplication提供了很多的觸發事件,每當工作流執行到某一狀態的時候,就會觸發該工作流里的方法,並且進行實時監控,所以目前工作流的啟動,都是使用該類來完成。
2. case:
定義一個winform窗體應用界面
button對應代碼如下:
private void btnStartWorkFlow_Click(object sender, EventArgs e) { //定義一個字典 var dict = new Dictionary<string, object>() { { "tempDateTime", DateTime.Now } }; //工作流的類, //WorkflowApplication wfApp = new WorkflowApplication(new Activity1()); //重載的第二種,傳遞一個參數過去,但是必須是鍵值對的形式。 WorkflowApplication wfApp = new WorkflowApplication(new Activity1(),dict); //信號量機制類 AutoResetEvent syncEvent = new AutoResetEvent(false); wfApp.Run(); }
工作流中如下:此處的參數必須和傳遞的參數值一致。
3. 常用觸發事件。
private void btnStartWorkFlow_Click(object sender, EventArgs ex) { Console.WriteLine("主線程:"+Thread.CurrentThread.ManagedThreadId); var dict = new Dictionary<string, object>() { { "TempDateTime", DateTime.Now }, { "TempBookMarkName",this.txtBookMarkName.Text} }; AutoResetEvent syncEvent = new AutoResetEvent(false); //主線程信號量 wfApp = new WorkflowApplication(new Activity1(), dict);//第二個參數是給工作流傳參,這里的參數名TempDateTime,必須和工作流中定義的參數名稱一致. //-----------------------常用觸發事件--------------------- //工作流執行完成之后觸發里面代碼, wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e) { Console.WriteLine("工作流執行完成"); syncEvent.Set(); //喚起主線程 }; //強制終止觸發 wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e) { Console.WriteLine("工作流終止"); syncEvent.Set(); }; //處於空閑狀態觸發 wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e) { Console.WriteLine("工作流空閑"); syncEvent.Set(); }; //工作流持久化,就是指例如把當前的數據錄入到數據庫中 wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) { Console.WriteLine("工作流持久化"); syncEvent.Set(); return PersistableIdleAction.Unload; //工作流卸載 }; //卸載之后觸發 wfApp.Unloaded = delegate(WorkflowApplicationEventArgs e) { Console.WriteLine("工作流卸載"); syncEvent.Set(); }; //發生異常觸發的時間 wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e) { Console.WriteLine("工作流異常了"); syncEvent.Set(); return UnhandledExceptionAction.Abort; }; // Start the workflow. wfApp.Run();//開始執行設計好的工作流,這里會會開啟一個新的線程。 syncEvent.WaitOne(); //阻止主線程,直到當前收到信號。 Console.WriteLine("繼續執行后面的代碼"); }
四、線程信號量類介紹:
1. new一個線程信號量
AutoResetEvent syncEvent = new AutoResetEvent(false); //主線程信號量
上方代碼中主要使用到了如下兩個方法;
syncEvent.Set(); //喚起主線程
syncEvent.WaitOne(); //阻止主線程,直到當前收到信號。
五、 BookMark(書簽)
1. 就是指執行到該結點處暫停,等待開啟的命令,然后繼續執行。
2. 就是指修改創建的代碼活動類。本來是繼承CodeActivity類,現在改為繼承NativeActivity,並且重新其中提供的抽象方法,注釋掉原本的方法,創建Bookmark書簽,需要提供兩個參數,一個是書簽名,一個是需要執行的方法,相關代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Activities; namespace WindowsFormsApplication1 { //修改使其繼承 NativeActivity public sealed class Wait4BookMarkCodeActivity :NativeActivity { // 定義一個字符串類型的活動輸入參數 public InArgument<string> BookMarkName { get; set; } public OutArgument<int> ReturnResult { get; set; } // 如果活動返回值,則從 CodeActivity<TResult> // 派生並從 Execute 方法返回該值。 //protected override void Execute(CodeActivityContext context) //{ // // 獲取 Text 輸入參數的運行時值 // string text = context.GetValue(this.Text); //} /// <summary> /// 自動調用該方法,在該方法中完成BookMark的創建 /// </summary> /// <param name="context"></param> protected override void Execute(NativeActivityContext context) { //拿到輸入參數的值 string bookMarkName = context.GetValue(BookMarkName); //創建bookMark,第一個是他的名字,第二個是傳遞一個委托事件 ,並且喚醒bookMark。 //以下等同於,第一個參數是名字,第二個參數是一個方法。 context.CreateBookmark(bookMarkName, ExecuteContinue); } protected override bool CanInduceIdle { get { return true; } } /// <summary> /// 當下次喚起BookMark,那么該方法被執行. /// </summary> /// <param name="context"></param> /// <param name="bookmark"></param> /// <param name="value"></param> public void ExecuteContinue(NativeActivityContext context, Bookmark bookmark, object value) { int i = Convert.ToInt32(value); context.SetValue(ReturnResult,i); } } }