天天看點

在UI上使用BackgroundWorker

凡是WinForm的應用程式,如果他執行了一個的非常冗長的處理操作(比如檔案查詢),它在執行時會鎖定使用者界面,雖然主活動視窗一直在運作,但使用者無法與程式互動,無法移動窗體或改變窗體大小,是以使用者感覺很不爽。如何做才能使得這個程式有響應。答案就是在背景線程中執行這個操作。

    在這裡已經有了多種方法來做這個事情:

    (一)委托異步調用

  将具體耗時的操作作為一個委托,并用BeginInvoke來異步執行這個委托(Invoke是同步調用),并且可以為這個操作傳入參數并且通過EndInvoke方法獲得傳回傳回值。

    (二)使用ThreadPool

  建立.net FrameWork中自帶的WaitCallback委托,然後放到線程池中運作ThreadPool.QueueUserWorkItem( callback ); 根據WaitCallback委托的定義,可以傳入一個object類型的參數。

但是不能精确的控制線程池中的線程。

    (三)使用Thread

            和ThreadPool相比,使用Thread的開銷會比較大。但是它有它的優勢,使用 Thread 類可以顯式管理線程。隻要有可能,就應該使用 ThreadPool 類來建立線程。然而,在一些情況下,您還是需要建立并管理您自己的線程,而不是使用 ThreadPool 類。在.net 2.0 中,提供了一個新的委托 ParameterizedThreadStart 支援啟動一個線程并傳入參數,這是對原來的ThreadStart委托的改進。

   說了這麼多還沒有說到今天的主角BackgroundWorker,他也是一個在2.0中新增的類,可以用于啟動背景線程,并在背景計算結束後調用主線程的方法.可以看出同樣的功能使用委托的異步調用也可以實作,隻是使用BackgroundWorker的話會更加的簡便快捷,可以節省開發時間,并把你從建立自己的委托以及對它們的調用中解救出來。真是這樣的嗎看看下面這個例子。其實我也是從101Samples中看到的例子。

   先看看BackgroundWorker中的主要概念。

   第一:主要的事件及參數。

          DoWork——當執行BackgroundWorker.RunWorkerAsync方法時會觸發該事件,并且傳遞DoWorkEventArgs參數;

          ProgressChanged——操作進行中獲得的處理狀态變化,通過BackgroundWorker.ReportProgress(int)方法觸發該事件,并且傳遞ProgressChangedEventArgs,其中包含了處理的百分比;

 RunWorkerCompleted ——異步操作完成後會觸發該事件,當然如果需要在操作過程中結束可以執行BackgroundWorker.CancelAsync方法要求異步調用中止,并且在異步委托操作中檢測BackgroundWorker.CancellationPending屬性如果為true的話,跳出異步調用,同時将 DoWorkEventArgs.Cancel屬性設為true,這樣當退出異步調用的時候,可以讓處理RunWorkerCompleted事件的函數知道是正常退出還是中途退出。

   第二:主要的方法。

         BackgroundWorker.RunWorkerAsync——

         “起動”異步調用的方法有兩次重載RunWorkerAsync(),RunWorkerAsync(object argument),第二個重載提供了一個參數,可以供異步調用使用。(如果有多個參數要傳遞怎麼辦,使用一個類來傳遞他們吧)。調用該方法後會觸發 DoWork事件,并且為處理DoWork事件的函數DoWorkEventArg事件參數,其中包含了RunWorkerAsync傳遞的參數。在相應 DoWork的處理函數中就可以做具體的複雜操作。

         BackgroundWorker.ReportProgress——

         有時候需要在一個冗長的操作中向使用者不斷回報進度,這樣的話就可以調用的ReportProgress(int percent),在調用 ReportProgress 方法時,觸發ProgressChanged事件。提供一個在 0 到 100 之間的整數,它表示背景活動已完成的百分比。你也可能提供任何對象作為第二個參數,允許你給事件處理程式傳遞狀态資訊。作為傳遞到此過程的 ProgressChangedEventArgs 參數屬性,百分比和你自己的對象(如果提供的話)均要被傳遞到 ProgressChanged 事件處理程式。這些屬性被分别命名為 ProgressPercentage 和 UserState,并且你的事件處理程式可以以任何需要的方式使用它們。(注意:隻有在 BackgroundWorker.WorkerReportsProgress屬性被設定為true該方法才可用)。

         BackgroundWorker.CancelAsync——

   但需要退出異步調用的時候,就調用的這個方法。但是樣還不夠,因為它僅僅是将BackgroudWorker.CancellationPending屬性設定為true。你需要在具體的異步調用處理的時候,不斷檢查BackgroudWorker.CancellationPending是否為 true,如果是真的話就退出。(注意:隻有在BackgroundWorker.WorkerSupportsCancellation屬性被設定為 true該方法才可用)。