可以編寫能同時執行多個任務的應用程序。此能力(稱為“多線程處理”或“自由線程處理”)是設計處理器密集型且要求用戶輸入的組件的強大方法。計算工資表信息的組件就是一個可能利用多線程處理的組件示例。該組件可以在一個線程上處理用戶輸入到數據庫的數據,而在另一個線程上執行頻繁使用處理器的工資表計算。通過在不同的線程上運行這些進程,用戶不必等到計算機完成計算,就可以輸入其他數據。在本演練中,將創建一個簡單的多線程組件,該組件可以同時執行若干個復雜計算。
創建項目
應用程序將包括單個窗體和一個組件。用戶將輸入值並指示該組件開始計算。然後,窗體將接收來自該組件的值,將其顯示在標簽控件中。該組件將執行頻繁使用處理器的計算,並在完成後通知窗體。您將在組件中創建公共變量,用以保存從用戶界面收到的值。同時,您還將在組件中實現一些方法,根據這些變量的值執行計算。
注意 盡管對於計算值的方法來說,函數通常更為可取,但不能在線程之間傳遞參數,也不能返回值。有很多向線程提供值和從線程接收值的簡單方法。在本演示中,將通過更新公共變量將值返回到用戶界面,當線程執行完畢後,使用事件來通知主程序。
創建窗體
創建新的“Windows 應用程序”項目。
將應用程序命名為 Calculations,並將 Form1.cs 重命名為 frmCalculations.cs。
該窗體將用作應用程序的主用戶界面。
雙擊設計器上的窗體以打開代碼編輯器。在“編輯”菜單中,選擇“查找和替換”,然後選擇“替換”。使用“全部替換”將 Form1 替換為 frmCalculations。
在“解決方案資源管理器”中,右擊“frmCalculations.cs”並選擇“視圖設計器”。設計器打開。
向窗體中添加 5 個 Label 控件、4 個 Button 控件和 1 個 TextBox 控件。
為這些控件設置屬性,如下所示:
控件名稱文本 Label1lblFactorial1(空白)Label2lblFactorial2 (空白) Label3lblAddTwo (空白)Label4lblRunLoops(空白)Label5lblTotalCalculations(空白)Button1btnFactorial1Factorial Button2 btnFactorial2Factorial - 1Button3 btnAddTwoAdd Two Button4btnRunLoopsRun a Loop Textbox1txtValue(空白)
創建 Calculator 組件
從“項目”菜單中選擇“添加組件”。
將組件命名為 Calculator。
向 Calculator 組件添加公共變量
為 Calculator 打開代碼編輯器。
添加創建公共變量的語句,這些變量用於將值從 frmCalculations 傳遞給每個線程。
變量 varTotalCalculations 將保留該組件執行的計算總數的累計值,而其他變量將接收來自窗體的值。
public int varAddTwo; public int varFact1; public int varFact2; public int varLoopValue; public double varTotalCalculations = 0;
向 Calculator 組件添加方法和事件
為事件聲明委托,組件將使用這些事件向窗體傳遞值。
注意 盡管您將聲明 4 個事件,但由於其中的兩個事件將具有相同的簽名,因此只需要創建 3 個委托。
緊接著上一步輸入的變量聲明的下方,鍵入下列代碼:
// This delegate will be invoked with two of your events. public delegate void FactorialCompleteHandler(double Factorial, double TotalCalculations); public delegate void AddTwoCompleteHandler(int Result, double TotalCalculations); public delegate void LoopCompleteHandler(double TotalCalculations, int Counter);
聲明組件將用來與應用程序進行通信的事件。為實現此目的,緊接著上一步輸入的代碼的下方,添加下列代碼。
public event FactorialCompleteHandler FactorialComplete; public event FactorialCompleteHandler FactorialMinusOneComplete; public event AddTwoCompleteHandler AddTwoComplete; public event LoopCompleteHandler LoopComplete;