本文主要記錄如何利用winform,BackgroundWorker線程控件和PRogressBar進度控件進行開發(這樣啟用工作線程和UI主線程,可以讓進度條能進行更新,避免UI假死),同時支持啟用多個后臺BackgroundWorker,以及支持統一的全局進度條更新,同時支持暫停和停止任務。
下面是定義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中調用具體執行的方法,worker_ProgressChanged方法用來實時更新進度條值,worker_RunWorkerCompleted方法用來處理當后臺線程執行完操作后要處理的事情,如更新界面UI進度條等。
剛開始的時候是沒有取消按鈕的,現在看看怎么加上取消按鈕。
BackgroundWorker 是支持取消事件的,主要通過一個button_click事件,調用Bworker .CancelAsync(),然后在worker_DoWork中檢測是否已經取消了:
//檢測是否被取消了if (worker.CancellationPending) { e.Cancel = true; break; } 有了取消,就想起了也需要加上暫停,暫停的功能需要自己實現。其實就是利用ManualResetEvent 允許線程通過發信號互相通信的特點,
1.設定一個全局的變量, public static ManualResetEvent mre = new ManualResetEvent(false);ManualResetEvent建立時是把false作為start的初始狀態,這個類用于通知另一個線程,讓它等待一個或多個線程。
2.增加一個暫停Pause_Click事件,如果是暫定,則調用 mre.Reset();//暫停當前線程的工作,發信號給waitOne方法,阻塞。
如果是繼續,則 mre.Set();//繼續某個線程的工作,
worker_DoWork中檢測mre.WaitOne();這樣就完成了簡單的暫停控制。
上面還是用單個線程處理事務,速度很慢,CPU,內存,IO都沒有充分的利用起來,所以下面就想到了啟用多線程,充分利用系統資源。
那么問題來了,如何結合BackgroundWorker使用多線程呢,后來發現其實一個簡單的做法,就是啟用多個BackgroundWorker來啟動業務,當然,對應的ManualResetEvent也需要有多個。(啟用多個BackgroundWorker唯一要注意的是更新全局變量進度的時候,需要針對進度進行加鎖)
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); }一個臨時轉換工具的開發過程,記錄下來,如上有什么更好建議或想法,也請大家多多指點。
新聞熱點
疑難解答