凡是WinForm的應(yīng)用程序,如果他執(zhí)行了一個(gè)的非常冗長(zhǎng)的處理操作(比如文件查詢),它在執(zhí)行時(shí)會(huì)鎖定用戶界面,雖然主活動(dòng)窗口 一直在運(yùn)行,但用戶無(wú)法與程序交互,無(wú)法移動(dòng)窗體或改變窗體大小,所以用戶感覺很不爽。如何做才能使得這個(gè)程序有響應(yīng)。答案就是在后臺(tái)線程中執(zhí)行這個(gè)操作。
在這里已經(jīng)有了多種方法來(lái)做這個(gè)事情:
(一)委托異步調(diào)用
將具體耗時(shí)的操作作為一個(gè)委托,并用BeginInvoke來(lái)異步執(zhí)行這個(gè)委托(Invoke是同步調(diào)用),并且可以為這個(gè)操作傳入?yún)?shù)并且通過EndInvoke方法獲得返回返回值。
(二)使用ThreadPool
新建.net FrameWork中自帶的WaitCallback委托,然后放到線程池中運(yùn)行ThreadPool.QueueUserWorkItem( callback ); 根據(jù)WaitCallback委托的定義,可以傳入一個(gè)object類型的參數(shù)。
但是不能精確的控制線程池中的線程。
(三)使用Thread
和ThreadPool相比,使用Thread的開銷會(huì)比較大。但是它有它的優(yōu)勢(shì),使用 Thread 類可以顯式管理線程。只要有可能,就應(yīng)該使用 ThreadPool 類來(lái)創(chuàng)建線程。然而,在一些情況下,您還是需要?jiǎng)?chuàng)建并管理您自己的線程,而不是使用 ThreadPool 類。在.net 2.0 中,提供了一個(gè)新的委托 ParameterizedThreadStart 支持啟動(dòng)一個(gè)線程并傳入?yún)?shù),這是對(duì)原來(lái)的ThreadStart委托的改進(jìn)。
說(shuō)了這么多還沒有說(shuō)到今天的主角BackgroundWorker,他也是一個(gè)在2.0中新增的類,可以用于啟動(dòng)后臺(tái)線程,并在后臺(tái)計(jì)算結(jié)束后調(diào)用主線程的方法.可以看出同樣的功能使用委托的異步調(diào)用也可以實(shí)現(xiàn),只是使用BackgroundWorker的話會(huì)更加的簡(jiǎn)便快捷,可以節(jié)省開發(fā)時(shí)間,并把你從創(chuàng)建自己的委托以及對(duì)它們的調(diào)用中解救出來(lái)。真是這樣的嗎看看下面這個(gè)例子。其實(shí)我也是從101Samples中看到的例子。
先看看BackgroundWorker中的主要概念。
BackGroundWorker是微軟提供的封裝好了的,非常實(shí)用的控件,我們可以在控件中將其拖到Winform之中,然后簡(jiǎn)單的系統(tǒng)生成代碼式的編輯事件處理。
以下是,比較經(jīng)典且簡(jiǎn)單的實(shí)用,后面的一篇較復(fù)雜,不使用微軟控件式,自行生成,并傳遞參數(shù)給多線程,并通過多線程更新主線程的多處UI,線程沒操作完一筆記錄,則報(bào)告進(jìn)度,更新UI。
下圖是微軟提供給我們的控件,拖到Winform中
我們可以看到有如下三個(gè)事件:
1、線程執(zhí)行的動(dòng)作,一般用于復(fù)雜操作,DoWork
2、線程進(jìn)度改變,進(jìn)度條變化
3、線程執(zhí)行完,這時(shí)候,又回到主線程執(zhí)行了,可以訪問主線程中的UI,操作主線程的UI
下列是最基本的核心代碼,只給出最核心部分,其他簡(jiǎn)單部分省略。
如果我主線程要傳遞參數(shù),以及多線程如何接受參數(shù),可以參考多線程按F12去查看微軟給出的操作,一般較多的是DataTable類型的,這個(gè)也是最常用的,可以參考筆者之前的關(guān)于多線程的一些比較實(shí)用的文章。
private void buttonTest_Click(object sender, EventArgs e) { BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.DoWork += Bw_DoWork; worker.ProgressChanged += Bw_ProgressChanged; worker.RunWorkerAsync(); } private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { labelProcess.Text = e.ProgressPercentage.ToString(); } private void Bw_DoWork(object sender, DoWorkEventArgs e) { var worker = sender as BackgroundWorker; for (int i = 0; i < 100; i++) { worker.ReportProgress(i); Thread.Sleep(100); } }
結(jié)果如下圖
如對(duì)本文有疑問,請(qǐng)?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答!! 點(diǎn)擊進(jìn)入論壇