转自:http://blog.csdn.net/zhongjiekangping/article/details/4563357(代码做了修改,原文中代码冗长)
特点:
BackgroundWorker 类允许在单独的专用线程上运行操作。
用途:
耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
若要在后台执行耗时的操作,请创建一个 BackgroundWorker,侦听那些报告操作进度,并在操作完成时发出信号的事件。
创建:
(1) 可以通过编程方式创建BackgroundWorker
(2) 可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
使用:
(1) 若要设置后台操作,请为 DoWork事件添加一个事件处理程序;
在此事件处理程序中调用耗时的操作。若要启动该操作,请调用 RunWorkerAsync();
(2) 若要收到进度更新通知,请对 ProgressChanged事件进行处理。若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。
注意:
您必须非常小心,确保在 DoWork事件处理程序中不操作任何用户界面对象;而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。
补充:
AppDomain类,表示应用程序域,它是一个应用程序在其中执行的独立环境。 此类不能被继承。
(3) 如果后台操作需要参数,请在调用 RunWorkerAsync() 时给出参数;在 DoWork事件处理程序内部,可以从 DoWorkEventArgs.Argument 属性中提取该参数。
有关 BackgroundWorker 的更多信息,请参见 如何:在后台运行操作。
注意:
应用于此类的 HostProtectionAttribute 属性 (Attribute) 具有以下 Resources 属性 (Property) 值: SharedState。
HostProtectionAttribute 不影响桌面应用程序(这些应用程序通常通过双击图标、键入命令或在浏览器中输入 URL 来启动)。
有关更多信息,请参见 HostProtectionAttribute 类或 SQL Server 编程和宿主保护属性。
BackgroundWorker类中主要用到的属性、方法和事件:
重要属性:
1、CancellationPending:获取一个值,指示应用程序是否已请求取消后台操作。
通过在DoWork事件中判断CancellationPending属性可以认定是否需要取消后台操作(也就是结束线程);
2、IsBusy:获取一个值,指示 BackgroundWorker 是否正在运行异步操作。
程序中使用IsBusy属性用来确定后台操作是否正在使用中;
3、WorkerReportsProgress:获取或设置一个值,该值指示BackgroundWorker能否报告进度更新
4、WorkerSupportsCancellation:获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。
设置WorkerSupportsCancellation为true,使得程序可以调用CancelAsync方法提交终止挂起的后台操作的请求;
重要方法:
1、CancelAsync:请求取消挂起的后台操作
2、RunWorkerAsync:开始执行后台操作
3、ReportProgress:引发ProgressChanged事件
重要事件(仅有的三个事件):
1、DoWork:调用 RunWorkerAsync 时发生
2、ProgressChanged:调用 ReportProgress 时发生
3、RunWorkerCompleted:当后台操作已完成、被取消或引发异常时发生
重要的参数(仅有的三个参数):
1、RunWorkerCompletedEventArgs(RunWorkerCompleted事件的参数)
主要的有三个属性:
1> Error 指示异步操作期间发生的错误
2>Cancelled 指示异步操作是否被取消
3> Result 获取异步操作的结果
2、DoWorkEventArgs(DoWork事件的参数)
最主要的是其Result属性,该属性存储计算的结果(Object类型),但须注意,该结果不能与UI进行交互
3、ProgressChangedEventArgs(ProgressChanged事件的参数)
最主要的是其ProgressPercentage属性,该属性可以反映后台工作的进展情况。
BackgroundWorker的各属性、方法、事件的调用机制和顺序:
从上图可见,在整个生命周期内发生了3次重要的参数传递过程:
参数传递1(传入参数):此次的参数传递是将RunWorkerAsync(Object)中的Object传递到DoWork事件的DoWorkEventArgs.Argument
由于在这里只有一个参数可以传递,所以在实际应用时,常封装一个类,将整个实例化的类作为RunWorkerAsync的Object传递到DoWorkEventArgs.Argument;
参数传递2(后台程序进度):此次是将程序运行进度传递给ProgressChanged事件,实际使用中往往使用给方法和事件更新进度条或者日志信息;
参数传递3(运行结果):在DoWork事件结束之前,将后台线程产生的结果数据赋给DoWorkEventArgs.Result,以便在RunWorkerCompleted事件中调用RunWorkerCompletedEventArgs.Result属性取得后台线程产生的结果。
另外从上图可以看到DoWork事件是在后台线程中运行的,所以在该事件中不能够操作用户界面的内容,如果需要更新用户界面,可以使用ProgressChanged事件及RunWorkCompleted事件来实现。
实例:
下面的代码示例演示如何使用 BackgroundWorker 类异步执行耗时的操作。该操作计算选定的斐波纳契数,在计算过程中报告进度更新,并允许取消挂起的计算。
用户界面如下:
增加了组件:BackGroundWork
成员变量:
//需要计算的Fibonacci private int m_calcNum; //计算进度 private int m_highestProcess;
Fibonacci的计算:
//递归计算Fibonacci数值 long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e) { // The parameter n must be >= 0 and <= 91. // Fib(n), with n > 91, overflows a long. //输入出错的话,抛出错误 if ((n < 0) || (n > 91)) { throw new ArgumentException("value must be >= 0 and <= 91", "n"); } long result = 0; //检查应用程序是否已经取消了后台操作 if (worker.CancellationPending) { e.Cancel = true; return 0; } //递归计算 if (n < 2) { result = 1; } else { result = ComputeFibonacci(n - 1, worker, e) + ComputeFibonacci(n - 2, worker, e); } // 任务进度的计算 int percentComplete =(int)((float)n / (float)m_calcNum * 100); if (percentComplete > m_highestProcess) { m_highestProcess = percentComplete; //报告计算进度 worker.ReportProgress(percentComplete); } return result; }开始计算按钮:
//开始计算 private void calcBtn_Click(object sender, EventArgs e) { //计算进度设为0 m_highestProcess = 0; //获取需要计算的Fibonacci数值 m_calcNum = int.Parse(CalcTextBox.Text); //开始异步执行后台程序 CalcBackgroundWorker.RunWorkerAsync(m_calcNum); }取消计算按钮:
//取消计算 private void cancelBtn_Click(object sender, EventArgs e) { //取消挂起的后台操作?? CalcBackgroundWorker.CancelAsync(); }组件的DoWork事件响应:
//组件的DoWork事件 //被RunWorkerAsync()调用 private void CalcBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { // Get the BackgroundWorker that raised this event. BackgroundWorker worker = sender as BackgroundWorker; //执行计算,并将结果存储在e.Result中 e.Result = ComputeFibonacci((int)e.Argument, worker, e); }组件的ProgressChanged事件:
//组件的ProgressChanged事件 private void CalcBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { CalProgressBar.Value = e.ProgressPercentage; }组件的RunWorkerCompleted事件:
//组件的RunWorkerCompleted事件,进行计算结束之后的处理 private void CalcBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // First, handle the case where an exception was thrown. if (e.Error != null) { MessageBox.Show(e.Error.Message); } else if (e.Cancelled) { //for test Console.WriteLine("操作已取消"); } else { // Finally, handle the case where the operation succeeded. ResultTextBox.Text = e.Result.ToString(); } }