2009-10-04 51 views
0

我在C#中編寫了一個Windows Forms應用程序,該應用程序執行大量長時間運行的過程。我需要編寫應用程序,以便GUI不鎖定。編程它的最佳方式是什麼?如何編程異步Windows Forms應用程序?

我知道如何使用下列內容:

  1. BeginInvoke/EndInvoke
  2. 調用Application.DoEvents()反覆(可能不是一個好主意)
  3. BackgroundWorker

但如何通過回叫等來管理GUI狀態......並不是微不足道的。是否有解決方案(以模式或庫的形式)?

回答

1

Model-View-Controller pattern將UI的狀態與UI的視覺方面分開。只要你的MVC實現是線程感知的,它應該爲你解決狀態管理問題。

這就是我如何處理多線程的UI實現。

編輯:這是good post關於爲WinForms項目選擇MVC實現。

+0

啊哈... that'w什麼MVC是。行..很多謝謝。 – Nestor 2009-10-04 20:54:14

0

使用ThreadPool從UI中觸發長時間運行的進程是相對簡單的。如果您需要反饋,可以使用一些事件處理程序從長時間運行的進程中觸發某些事件,然後註冊並根據需要更新UI。

MVC很好,但你仍然需要確保你的進程在UI線程以外的線程上觸發。

0

所有的選項都是做同樣事情的語法糖(異步執行)。可能會有不同程度的控制。我會去BackgroundWorker,因爲你的GUI(由主線程處理)將始終是響應式的。

2

使用BackgroundWorker是最簡單的方法來做你想做的事情。 BackgroundWorker簡化了處理線程的邏輯,讓您只需很少的代碼即可編寫代碼。你只需要處理三個事件(DoWorkProgressChangedRunWorkerCompleted),並遵循幾個原則:

  • 永遠不要更新您的長時間運行的方法中的UI。讓它調用ReportProgress,並在UI邏輯中處理ProgressChanged事件。
  • 瞭解,由於工作人員未在UI線程上運行,因此您的方法拋出的異常不會自動顯示在UI中。它只是悄悄地寫入控制檯。當方法完成並處理(或拋出)異常時,檢查RunWorkerCompletedEventArgsError屬性非常重要。如果你不這樣做,你就不會知道你的方法失敗了。
  • 如果方法可以取消,請確保它定期檢查CancellationPending屬性以查看是否已請求取消。如果有,一旦完成處理取消操作,請在DoWorkEventArgs對象上設置Cancel屬性。請注意,有可能CancellationPending爲真,Cancel爲假;例如,當用戶請求取消並且該方法在它有機會檢查CancellationPending之前完成時發生這種情況。
  • 相應地,檢查CancelRunWorkerCompleted事件處理程序,讓你的UI可以提供,而工人正在運行什麼事適當的反應。

文檔中的示例都顯示調用窗體方法的DoWork事件處理函數。這幾乎肯定不是你想要做的。一般來說,將業務邏輯與用戶界面分離是一個好主意;在後臺任務中這是至關重要的。如果你的長時間運行的方法是一個不知道UI甚至存在的類的成員,那麼你就不會有無意中讓它調用更新狀態欄或其他方法的方法。

相關問題