在一个程序中,一些耗时的操作,在长时间运行时可能会导致用户界面 (UI) 处于停止响应状态,用户在这操作期间无法进行其他的操作,为了不使UI层处于停止响应状态,需要将这些耗时的操作,设置为后台线程,并且在UI层可以展示后台操作的进度,比较常用的方法有使用线程以及BackgroundWorker类。
1、线程方法
当我们要在前太展示后台的操作进程时,是不允许跨线程访问控件。此时需要取消控件的跨线程访问,在winform中可以设置CheckForIllegalCrossThreadCalls = false,而在wpf中不存在CheckForIllegalCrossThreadCalls 这个属性,在这介绍一种方法,取消跨线程访问,在wpf中有Dispatcher属性使用委托的方法来告诉控件需要做什么。
public Action<int> proBarDel;//先定义一个委托 /// <summary> /// 取消夸线程访问 /// </summary> /// <param name="str"></param> private void CrossThread(int i) { //取消控件夸线程访问 proBarDel = this.GetReceive; this.pb.Dispatcher.Invoke(proBarDel, i); this.lab1.Dispatcher.Invoke(proBarDel, i); } /// <summary> /// 为控件设置内容 /// </summary> /// <param name="receiveStr"></param> public void SetValue(int receive) { pb.Value = receive; lab1.Content = receive; }
//在按钮的点击事件中新增一个线程
Thread th = new Thread(() => {
for (int i = 0; i <= 100; i++)
{
CrossThread(i);//将执行的进度汇报给UI层的控件
Thread.Sleep(100);
}
});
th.IsBackground = true;
th.Start();
当点击开始按钮时进度条就会显示进度
2、使用BackgroundWorker
BackgroundWorker 类允许在单独的专用线程上运行操作,使用BackgroundWorker 需要引用System.ComponentModel
BackgroundWorker 有三个重要的事件
this.bgWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
this.bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
this.bgWorker.ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
DoWork(),将需要处理的后台操作放入DoWork()中
BackgroundWorker bgWorker = new BackgroundWorker();//创建一个BackgroundWorker
/// <summary> /// 需要处理的事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { e.Result = DoWork(bgWorker, e); } private bool DoWork(BackgroundWorker bk,DoWorkEventArgs e) { int num = (int)e.Argument;// int p = 0; for (int i = 0; i < num; i++) { if (bk.CancellationPending)//判断是否取消后台操作 { return false; } else { p = (int)(((double)i / (double)num )* 100); bk.ReportProgress(p);//报告进度 Thread.Sleep(100); } } return true; }
ProgressChanged调用 ReportProgress 时发生
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { proBar.Value = e.ProgressPercentage;//获得进度给进度条 this.lab1.Content = e.ProgressPercentage; }
RunWorkerCompleted 后台操作执行完成时或取消时发生
/// <summary> /// 处理完成 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { MessageBox.Show("ok"); }
在使用BackgroundWorker 报告后台的进度时需要将 WorkerReportsProgress 设置为true,否则在bk.ReportProgress(p)报告进度是会抛出异常
以上只是个人使用的总结,不是很全面,希望大家补充,有错误的地方希望能够指出
在MSDN中有对BackgroundWorker的详细的讲解https://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx