轉載:https://www.cnblogs.com/atskyline/archive/2012/06/22/2558516.html
簡介
但凡涉及到圖形界面,往往的設計都是不支持或者不推薦使用多個線程操作界面內容.而且通常會有一個專門的線程調度器來處理任務線程和界面線程的問題.下面提供兩個兩個方案.
使用Dispatcher.BeginInvoke
這個方法簡單暴力適合小工作量的修改一些界面內容.使用Dispatcher.BeginInvoke()會將代碼安排為調度程序的一個任務.
步驟
- 使用Thread新建並開始一個線程
- 在新建的線程處理函數中需要修改界面的時候獲取界面的dispatcher
- 使用Dispatcher的BeginInvoke方法指定一個線程優先級,和一個委托,這個委托時用於修改界面內容的
下面給出一部分代碼
//新建線程 Thread thread = new Thread(UpdateTextRight); thread.Start();
下面是新線程中的方法
//這個事例剛好是先窗體類中定義的,所以獲取Dispatcher變得比較方便,而且使用了匿名委托.在通常的代碼中會把委托給分離出去比較好. private void UpdateTextRight() { this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) delegate() { txt.Text = "Here is some new text."; } ); }
使用BackgroupWorker
這個類是專門用於簡化Windows Form程序與線程相關的問題設計的,同樣適用於WPF程序.適合於一個長期的后台進程,支持進度通知,取消支持,完成通知等功能.
使用方法也很簡單,創建一個BackfruopWorker實例,它有幾個事件.
DoWork事件會在另外一個線程中執行,用RunWorkerAsync()啟動.所以在這個事件中不要去處理修改界面的事情
RunWorkerCompleted事件,在DoWork事件返回時(正常或者異常返回),在圖形的線程中執行,所以可以修改界面
ProgressChanged事件,使用ReportProgress()方法調用,同時是在圖形界面的線程中執行,通常負責修改一下進度條什么的.而ReportProgress()方法,通常會在DoWork的事件中調用,然后給一個百分比的值.要使用這個功能,需要把WorkerReportsProgress屬性設置成true
另外值得一說的是,要取消支持需要把WorkerSupportsCancellation屬性設為true,使用CancelAsync()方法調用,但是這個調用不會終止進程,所以在DoWork事件中需要判斷CancellationPending.
下面給出部分代碼
創建BackgroundWorker實例
BackgroundWorker backgroundWorker; backgroundWorker = new BackgroundWorker(); backgroundWorker.DoWork += backgroundWorker_DoWork; backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; //可以返回工作進度 backgroundWorker.WorkerReportsProgress = true; backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged; //允許取消 backgroundWorker.WorkerSupportsCancellation = true;
開始執行DoWork
backgroundWorker.RunWorkerAsync();
DoWork事件范例,這個方法的內容是在另外一個線程,異步執行得
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { while(!backgroundWorker.CancellationPending) { //Do SomeThing //在合適的時候使用 //backgroundWorker.ReportProgress(i); //報告一下進度,其中i是0-100的整數 } //這里可以使用e.Result給一個返回值,如果有需要的話 }
進度改變時的處理事件,也就是修改一下進度條什么的
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar.Value = e.ProgressPercentage; }
完成事件我就不演示,下面是取消任務的方法
private void cmdCancel_Click(object sender, RoutedEventArgs e) { backgroundWorker.CancelAsync(); }