本文主要記錄如何利用winform,BackgroundWorker線程控件和PRogressBar進(jìn)度控件進(jìn)行開(kāi)發(fā)(這樣啟用工作線程和UI主線程,可以讓進(jìn)度條能進(jìn)行更新,避免UI假死),同時(shí)支持啟用多個(gè)后臺(tái)BackgroundWorker,以及支持統(tǒng)一的全局進(jìn)度條更新,同時(shí)支持暫停和停止任務(wù)。
下面是定義BackgroundWorker各種事件:
BackgroundWorker Bworker = new BackgroundWorker(); Bworker.WorkerReportsProgress = true;Bworker.DoWork += new DoWorkEventHandler(worker_DoWork);Bworker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);Bworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);Bworker.RunWorkerAsync();在work_DoWork中調(diào)用具體執(zhí)行的方法,worker_ProgressChanged方法用來(lái)實(shí)時(shí)更新進(jìn)度條值,worker_RunWorkerCompleted方法用來(lái)處理當(dāng)后臺(tái)線程執(zhí)行完操作后要處理的事情,如更新界面UI進(jìn)度條等。
剛開(kāi)始的時(shí)候是沒(méi)有取消按鈕的,現(xiàn)在看看怎么加上取消按鈕。
BackgroundWorker 是支持取消事件的,主要通過(guò)一個(gè)button_click事件,調(diào)用Bworker .CancelAsync(),然后在worker_DoWork中檢測(cè)是否已經(jīng)取消了:
//檢測(cè)是否被取消了if (worker.CancellationPending) { e.Cancel = true; break; } 有了取消,就想起了也需要加上暫停,暫停的功能需要自己實(shí)現(xiàn)。其實(shí)就是利用ManualResetEvent 允許線程通過(guò)發(fā)信號(hào)互相通信的特點(diǎn),
1.設(shè)定一個(gè)全局的變量, public static ManualResetEvent mre = new ManualResetEvent(false);ManualResetEvent建立時(shí)是把false作為start的初始狀態(tài),這個(gè)類用于通知另一個(gè)線程,讓它等待一個(gè)或多個(gè)線程。
2.增加一個(gè)暫停Pause_Click事件,如果是暫定,則調(diào)用 mre.Reset();//暫停當(dāng)前線程的工作,發(fā)信號(hào)給waitOne方法,阻塞。
如果是繼續(xù),則 mre.Set();//繼續(xù)某個(gè)線程的工作,
worker_DoWork中檢測(cè)mre.WaitOne();這樣就完成了簡(jiǎn)單的暫停控制。
上面還是用單個(gè)線程處理事務(wù),速度很慢,CPU,內(nèi)存,IO都沒(méi)有充分的利用起來(lái),所以下面就想到了啟用多線程,充分利用系統(tǒng)資源。
那么問(wèn)題來(lái)了,如何結(jié)合BackgroundWorker使用多線程呢,后來(lái)發(fā)現(xiàn)其實(shí)一個(gè)簡(jiǎn)單的做法,就是啟用多個(gè)BackgroundWorker來(lái)啟動(dòng)業(yè)務(wù),當(dāng)然,對(duì)應(yīng)的ManualResetEvent也需要有多個(gè)。(啟用多個(gè)BackgroundWorker唯一要注意的是更新全局變量進(jìn)度的時(shí)候,需要針對(duì)進(jìn)度進(jìn)行加鎖)
private List<ManualResetEvent> lstManualResets = null; private BackgroundWorker Bworker = null; private static readonly object objLock = new object(); for (int i = 0; i < nThreadNum; i++) { Bworker = new BackgroundWorker(); Bworker.WorkerSupportsCancellation = true; Bworker.WorkerReportsProgress = true; Bworker.DoWork += new DoWorkEventHandler(worker_DoWork); Bworker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); Bworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); lstBworkers.Add(Bworker); lstManualResets.Add(new ManualResetEvent(true)); Bworker.RunWorkerAsync(i); }一個(gè)臨時(shí)轉(zhuǎn)換工具的開(kāi)發(fā)過(guò)程,記錄下來(lái),如上有什么更好建議或想法,也請(qǐng)大家多多指點(diǎn)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注