問題引出:
winform程序中的耗時操作,一般不能在UI線程中執行,需要另開線程。往往我們需要在耗時操作結束後將結果顯示在UI上。
以下是Mainform.cs中調用耗時操作的一段代碼:
1 Job j = new Job(); 2 j.runJob();
這裡耗時操作被封裝在類Job中,調用 j.runJob() 開始耗時操作。其中runJob中封裝了開啟新線程執行任務的代碼。
Job運行完後需要返回一個結果並顯示在UI上。
顯而易見的方法是,在Job中實例化一個Mainform對象,然後直接在Job中對UI進行修改。這種方法極其不提倡,極大的增加了類之間的耦合性。
可以想到的一種合理的方法,Job類完成了耗時任務之後給調用它的類發送“消息”,”消息“中還包括了應該顯示的結果。Job方還應該做到:只管發送”消息“,而不管發送給誰。這樣就算更換了調用方,Job類的代碼也不需要進行修改。這樣的”消息“在C#中即為”事件“。
方法步驟:
1.在Job類(需要調用其他類中方法的類)中聲明這兩個變量:
1 public delegate void FinishHandler(int param); //聲明委托 2 public event FinishHandler FinishEvent; //聲明事件
委托的變量名可隨意命名,括號中定義了要傳遞參數的類型和個數,這裡需要傳遞一個int變量。
第二行事件的類型要於委托的名稱一樣。
2.在Job類(需要調用其他類中方法的類)中合適的地方調用事件:
1 FinishEvent(score);
合適的地方一般來說就是耗時操作結束,需要返回結果時。
括號內參數形式與個數要與第一步中定義的一致。
3.將事件發生時需要執行的方法注冊到事件中
1 Job j = new Job(); 2 j.FinishEvent += updateData; 3 j.runJob();
當然,updateData的參數形式和個數也和第一步時一樣。
分析總結:
梳理一下運行程序時發生了什麼。
實際運行時,首先運行的是第3步中的三行代碼。
第二行表示updateData方法會被j對象中的FinishEvent事件觸發。
第三行開始運行耗時任務,Job類在執行到任務結束准備返回數據時,來到了第二步中的那行代碼,此時,會觸發所有注冊了該事件的方法開始執行。
這樣從MainForm的角度看,實現了異步調用,耗時任務的結果通過另一個函數讀取。
從Job類的角度看,調用了另一個類中的方法。
更多應用待之後編程實踐中發現。