一、概述
1、BackgroundWorker 类允许您在单独的专用线程上运行操作,在界面上报告进度,接受界面的控制信号,返回运算结果。
2、BackgroundWorker 的DoWork代码运行在非UI线程之上,BackgroundWorker 不跨 AppDomain 边界进行封送处理。
3、BackgroundWorker 是基于事件的异步编程模式EAP的复杂实现。
二、BackgroundWorker 配置
1、初始化BackgroundWorker
主要需要对BackgroundWorker 绑定一下三个事件:
- 开始工作的事件:DoWork——非UI线程执行,不可操作界面控件对象
- 完成工作的事件:RunWorkerCompleted——UI线程执行
- 工作中刷新的事件:ProgressChanged——UI线程执行
public static void BackgroundWorker1_Init() { BackgroundWorker backgroundWorker1 = new BackgroundWorker(); backgroundWorker1.WorkerReportsProgress = true;//能否报告进度更新。 backgroundWorker1.WorkerSupportsCancellation = true;//是否支持异步取消 //绑定事件 backgroundWorker1.DoWork += new DoWorkEventHandler(BackgroundWorker1_DoWork); backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker1_ProgressChanged); backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted); //启动BackgroundWorker if (backgroundWorker1.IsBusy != true)//判断BackgroundWorker 是否正在运行异步操作。 { backgroundWorker1.RunWorkerAsync("object argument");//启动异步操作,有两种重载(有参和无参),将触发BackgroundWorker.DoWork事件 } }
2、DoWork开始事件
/// <summary> /// 句柄sender指向的就是该BackgroundWorker。 /// e.Argument 获取异步操作参数的值 /// e.Cancel 是否应该取消事件 /// e.Result 获取或设置异步操作结果的值(在RunWorkerCompleted事件可能会使用到) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { object value = e.Argument;//获取RunWorkerAsync(object argument)传入的值 BackgroundWorker worker = sender as BackgroundWorker; for (int i = 1; i <= 10; i++) { if (worker.CancellationPending == true)//在耗时操作中判断CancellationPending属性,如果为true则退出 { e.Cancel = true; break; } else { // 执行耗时操作 System.Threading.Thread.Sleep(1000); worker.ReportProgress(i * 10, "Object userState");// 将触发BackgroundWorker.ProgressChanged事件,向ProgressChanged报告进度 } } e.Result = "结束"; }
3、RunWorkerCompleted完成事件
当DoWork事件处理完成之后,将会触发该事件处理工作结果。事件可根据传入的参数e来区分工作是中止或完成。
/// <summary> /// e.Cancelled指示异步操作是否已被取消 /// e.Error 指示异步操作期间发生的错误 /// e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //判断是否用户手动取消,若程序要支持此处功能,需要程序中有cancel的动作,并在该动作中将e.cancel置为true if (e.Cancelled == true) { //添加用户手动取消的动作,并在标签控件中进行提示 Console.WriteLine($"操作已经被取消!"); } //判断是否由错误造成意外中止 else if (e.Error != null) { //若发生错误,在标签控件中显示错误信息 Console.WriteLine($"操作发生错误!"); } //判断是否正常结束 else { //添加正常结束之后的收尾动作,并在标签控件中进行提示 Console.WriteLine($"执行结果:{e.Result.ToString()}!"); } }
4、ProgressChanged刷新事件
更新进度条的进度,此处也可以加入用户在过程中需要实时刷新的内容
/// <summary> /// 进度刷新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { //接收ReportProgress方法传递过来的userState string state = (string)e.UserState; //e.ProgressPercentage 获取异步操作进度的百分比 Console.WriteLine($"进度:{e.ProgressPercentage.ToString() + "%"};状态:{state}"); }
5、取消BackgroundWorker
取消BackgroundWorker 需要在DoWork中循环检查BackgroundWorker.CancellationPending是否为true。
//终止 private void BackgroundWorker1_End() { if (backgroundWorker1.WorkerSupportsCancellation == true) { // Cancel the asynchronous operation. backgroundWorker1.CancelAsync(); //请求取消挂起的后台操作。调用该方法将使BackgroundWorker.CancellationPending属性设置为True。 } }
三、完整的代码

using System; using System.ComponentModel; namespace BackgroundWorkerDemo { public class BackgroundWorkerInit { public static void BackgroundWorker1_Init() { BackgroundWorker backgroundWorker1 = new BackgroundWorker(); backgroundWorker1.WorkerReportsProgress = true;//能否报告进度更新。 backgroundWorker1.WorkerSupportsCancellation = true;//是否支持异步取消 //绑定事件 backgroundWorker1.DoWork += new DoWorkEventHandler(BackgroundWorker1_DoWork); backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorker1_ProgressChanged); backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted); //启动BackgroundWorker if (backgroundWorker1.IsBusy != true)//判断BackgroundWorker 是否正在运行异步操作。 { backgroundWorker1.RunWorkerAsync("object argument");//启动异步操作,有两种重载(有参和无参),将触发BackgroundWorker.DoWork事件 } } /// <summary> /// 句柄sender指向的就是该BackgroundWorker。 /// e.Argument 获取异步操作参数的值 /// e.Cancel 是否应该取消事件 /// e.Result 获取或设置异步操作结果的值(在RunWorkerCompleted事件可能会使用到) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { object value = e.Argument;//获取RunWorkerAsync(object argument)传入的值 BackgroundWorker worker = sender as BackgroundWorker; for (int i = 1; i <= 10; i++) { if (worker.CancellationPending == true)//在耗时操作中判断CancellationPending属性,如果为true则退出 { e.Cancel = true; break; } else { // 执行耗时操作 System.Threading.Thread.Sleep(1000); worker.ReportProgress(i * 10, "Object userState");// 将触发BackgroundWorker.ProgressChanged事件,向ProgressChanged报告进度 } } e.Result = "结束"; } /// <summary> /// e.Cancelled指示异步操作是否已被取消 /// e.Error 指示异步操作期间发生的错误 /// e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //判断是否用户手动取消,若程序要支持此处功能,需要程序中有cancel的动作,并在该动作中将e.cancel置为true if (e.Cancelled == true) { //添加用户手动取消的动作,并在标签控件中进行提示 Console.WriteLine($"操作已经被取消!"); } //判断是否由错误造成意外中止 else if (e.Error != null) { //若发生错误,在标签控件中显示错误信息 Console.WriteLine($"操作发生错误!"); } //判断是否正常结束 else { //添加正常结束之后的收尾动作,并在标签控件中进行提示 Console.WriteLine($"执行结果:{e.Result.ToString()}!"); } } /// <summary> /// 进度刷新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { //接收ReportProgress方法传递过来的userState string state = (string)e.UserState; //e.ProgressPercentage 获取异步操作进度的百分比 Console.WriteLine($"进度:{e.ProgressPercentage.ToString() + "%"};状态:{state}"); } } }
using System; namespace BackgroundWorkerDemo { class Program { static void Main(string[] args) { BackgroundWorkerInit.BackgroundWorker1_Init(); Console.ReadKey(); } } }
执行结果: