耗时的操作在长时间运行时可能导致用户界面停止响应,这时需要把操作转移到单独的线程上运行,保证当前用户界面可以继续流畅交互,同时还需要实时了解独立线程上的任务进度。可以使用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(); } } }
时间: 2024-11-05 02:22:31