耗時的操作在長時間運行時可能導致用戶界面停止響應,這時需要把操作轉移到單獨的線程上運行,保證當前用戶界面可以繼續流暢交互,同時還需要實時了解獨立線程上的任務進度。可以使用BackgroudWorker解決此類問題。
假設當前線程為主線程,執行耗時任務的線程為獨立線程。
需要創建一個BackgroudWorker對象,主要關注這幾個事件:
DoWork:當發出執行后台的信息后,會觸發這個事件,響應該事件的方法是處理后台任務的主體。注意:處理該事件的方法不可以調用主線程的控件。
ProgressChanged:在任務執行過程中,適當時機報告工作進度,此時會觸發該事件。注意:處理該事件的方法可以調用主線程的控件。
RunWorkerCompleted:無論任務如何結束,可能顯式停止,也可能發生了異常,此時會觸發該事件。注意:處理該事件的方法可以調用主線程的控件。
public partial class Form1 : Form { private BackgroundWorker backgroundWorker1; public Form1() { InitializeComponent(); radProgressBar1.Minimum = 0; radProgressBar1.Maximum = 100; radProgressBar1.Step = 1; radProgressBar1.Value1 = 0; backgroundWorker1 = new BackgroundWorker { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; backgroundWorker1.DoWork += Dowork; backgroundWorker1.ProgressChanged += ProgressChanged; backgroundWorker1.RunWorkerCompleted += RunWorkerCompleted; } //啟動任務 private void button2_Click(object sender, EventArgs e) { if (backgroundWorker1.IsBusy != true) { backgroundWorker1.RunWorkerAsync(); } } //執行任務 private void Dowork(object sender, DoWorkEventArgs e) { var worker = sender as BackgroundWorker; worker.WorkerReportsProgress = true; for (int i=1; i <= 10; i++) { if (worker.CancellationPending) { e.Cancel = true; break; } else { Thread.Sleep(500); worker.ReportProgress(i * 10);//報告工作進度 } } } //處理進度報告,此處可以使用主線程的控件 private void ProgressChanged(object sender, ProgressChangedEventArgs e) { radProgressBar1.Value1 = e.ProgressPercentage * radProgressBar1.Maximum / 100; } //任務不管以何種方式結束,在該方法中善后 private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { radProgressBar1.Value1 = 0; //todo 取消執行的操作 } else if (e.Error != null) { radProgressBar1.Value1 = 0; //todo 發生錯誤時執行的操作 } else { //todo } } //停止線程的操作 private void button3_Click(object sender, EventArgs e) { if (backgroundWorker1.WorkerSupportsCancellation) { backgroundWorker1.CancelAsync(); } } }