这是一个在.net2.0里面新出现的类,用于执行后台比较长的任务而又想能和UI有点操作的应用里面。
普通情况下,你点击一个按钮,去后台执行一个process,如果你想得到结果,就得等这个process结束。通常,可以使用异步执行回调来解决这个问题。现在,backgroundworker给我们实现了这样一种简单的封装,可以把我们的复杂任务交给新的线程去处理,然后继续UI线程。等到我们的任务需要通知UI做什么事情的时候,可以report一下,在其事件里就可以直接使用UI控件,而不需要Control.Invoke去掉用之。
有这样一个应用:客户需要把大量数据(需要执行3天)copy到另外一个机器,中间想能看到有多少数据被复制/失败等(实时报道)。
在这个例子里面,我们的界面可能非常简单:一个开始按钮,一个结束按钮,一个richtextBox来显示运行记录。但是后台执行可能就会比较棘手。如果简单的执行,并且报告,那么整个界面将失去响应(都在同一个线程里面,造成忙碌)。这时候,可以使用这个backgroundworker了。它可以在后台执行,并且报告给界面实时信息,界面不会失去响应。
先介绍一下backgroundworker的几个属性/方法
.WorkerReportsProgress:是否可以向外报告进度。
.WorkerSupportsCancellation :是否可以暂停任务
. CancellationPending: 是否正在暂停中
. RunWorkerAsync() : 开始执行任务。触发DoWork事件
. ReportProgress(int percentPrgress,object userState) : 向外报告进度。触发ProgressChanged事件.其中,参数可以在ProgressChangedEventArgs(worker_ProgressChanged(object sender, ProgressChangedEventArgs e))中得到
. CancelAsync() :取消(暂停)执行。
事件
worker.DoWork += new DoWorkEventHandler(worker_DoWork);//执行任务
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);//任务结束时
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged)//报告状态
按照上边的资料,我们这个应用就可以这样处理之
formDisplay是用于显示实时状态的窗口。有DisplyMessage方法来显示信息到界面
在Hanlder类(处理文件copy的)里面:
static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//show the message on windows
formDisplay.DisplyMessage(“copy”, e.UserState.ToString());//show message.
}
static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string msg = "JOB copy : have been completed";
formDisplay.DisplyMessage(msg);//show message
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
for(…)
{
//copying
(sender as BackgroundWorker). ReportProgress(0,”xxx complete”);//report
}
}
这样构造的程序里面,才不会出现UI失去响应。
当然,通过写自己的异步处理也可以实现,功能更强大。只不过这个用起来更简单。
至于backgroundworker是怎么实现的呢?这里有人已经做出了一些解答:
http://blog.joycode.com/sunmast/archive/2006/03/02/about_system_componentmodel_asyncoperation.aspx实例:
耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面处于停止响应状态,这样会让程序显得很笨很慢。
解决的办法就是在窗体里创建一个BackgroundWorker,通过它,你可以让那些耗时的操作都在后台运行,并时刻报告运行的进度,而且窗体仍然可以照常响应其他操作。
具体操作如下:
1、创建BackgroundWorker
从“工具箱”的“组件”选项卡中把“BackgroundWorker”拖到窗体上。如果在 Windows 窗体设计器中创建BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
有两个属性:
this.backgroundWorker1.WorkerReportsProgress = true; //是否报告进度
this.backgroundWorker1.WorkerSupportsCancellation = true; //是否支持取消进程
2、创建三个事件:
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
//开始事件
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
InvokeFun(worker, e);
}
//完成事件
private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
MessageBox.Show("Cancelled.");
}
else
{
MessageBox.Show("Completed");
}
}
//进度变化事件
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage; //增加进度条数值
}
3、后台操作程序
//在后台运行的操作
private void InvokeFun(BackgroundWorker worker, DoWorkEventArgs e)
{
for (int i = 1; i <= pagecount; i++)
{
if (worker.CancellationPending)
{
e.Cancel = true;
}
else
{
//操作...
////////////////////////////////////////////
percentComplete = (int)((float)i / (float)pagecount * 100);
worker.ReportProgress(percentComplete);
}
}
4、两个按钮
//开始按钮
private void buttonStart_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
//取消按钮
private void buttonCancel_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
}
5、using System.Threading;