本文主要介绍C# BackgroundWorker的详细使用说明。边肖认为这很好。现在分享给大家,给大家一个参考。来和边肖一起看看吧。
在C#程序中,经常会有一些CPU密集型的操作需要很长时间。如果直接在UI线程中执行此类操作,UI将不会响应。解决这类问题的主要方法是使用多线程,启动一个后台线程,把操作放在这个后台线程中完成。但是原生接口的线程操作存在一些困难,如果要进一步完成线程间的通信会更加困难。
幸运的是。NET类库提供了一个名为BackgroundWorker的类,可以很好地解决这类问题。尽管BackgroundWorker类使用起来相对简单,但仍有一些细节需要注意。这里我们将通过演示程序介绍它的主要用法。我们在演示中计算1到100的累积和。为了演示,每个计算休眠600毫秒。演示的用户界面是:
用法概述
在窗体上构建一个BackgroundWorker实例,向其DoWork事件处理程序添加耗时的操作,然后调用其RunWorkerAsync方法。
private background worker _ demoBGWorker=new background worker();
_demoBGWorker。DoWork=BGWorker _ DoWork
_demoBGWorker。RunWorkerAsync();
私有void BGWorker_DoWork(对象发送方,DoWorkEventArgs e)
{
//在此执行耗时的操作。
int sum=0;
for(int I=0;i=100我)
{
sum=I;
}
}
是不是有点太简单了?那么让我们考虑以下几个问题:
如果要给操作过程传递参数,应该怎么做?
如果想在操作过程中在UI上显示实时信息,应该怎么做?
如果我们想取消正在进行的操作,应该怎么做?
手术过程异常怎么办?
接下来,我们将逐一处理这些问题。
把参数传递给运算过程
直接把100写进计算过程不好。我们还打算允许用户指定求和的范围!所以您需要将100作为参数传递给计算过程。在概述中,我们通过调用RunWorkerAsync方法开始计算过程,该方法实际上可以接受一个对象类型参数。通过它,我们可以将任何数据传递给计算过程:
//别忘了设置滚动条。
this . progressbarsum . maximum=100;
_demoBGWorker。RunWorkerAsync(100);
//下面是更新后的BGWorker_DoWork方法:
私有void BGWorker_DoWork(对象发送方,DoWorkEventArgs e)
{
//在此执行耗时的操作。
int end number=0;
if(e.Argument!=空)
{
endNumber=(int)e . Argument;
}
int sum=0;
for(int I=0;i=endNumber我)
{
sum=I;
}
}
BGWorker_DoWork事件处理程序通过参数e的Argument属性发送预期的操作信息。
把消息传递给UI
由于计算过程较长,我们希望在通过进度条显示当前进度的同时,在UI上实时显示计算的中间结果。当然,BackgroundWorker也为这个用例提供了很好的支持。它允许我们在计算过程中向UI线程发送消息。以下是如何做到这一点:
_demoBGWorker。WorkerReportsProgress=true
_demoBGWorker。progress changed=BGWorker _ progress changed;
首先,将WorkerReportsProgress属性设置为true,然后添加ProgressChanged事件的处理方法:
private void BGWorker _ progress changed(对象发送方,ProgressChangedEventArgs e)
{
//修改进度条的显示。
this . progress bar sum . value=e . progress percentage;
//如果需要传递更多信息,可以使用e.UserState传递自定义类型。
//这是一个object类型的对象,通过它可以传递任何类型。
//我们只通过e.UserState返回当前sum的值,并通过在窗口上显示。
string message=e . userstate . tostring();
this . label sum . text=message;
}
继续更新BGWorker_DoWork方法:
私有void BGWorker_DoWork(对象发送方,DoWorkEventArgs e)
{
background worker BG worker=sender as background worker;
int end number=0;
if(e.Argument!=空)
{
endNumber=(int)e . Argument;
}
int sum=0;
for(int I=0;i=endNumber我)
{
sum=I;
string message='当前总和为:' sum。ToString();
////report progress方法将信息传递给ProcessChanged事件处理程序。
//第一个参数类型是int,表示执行进度。
//如果需要传递更多信息,可以使用ReportProgress的第二个参数。
//这里我们为第二个参数传入一条消息。
bgWorker。ReportProgress(i,message);
线程。睡眠(600);
}
}
好了,现在你可以看到进度条并更新执行信息了。
取消操作
允许用户在执行过程中取消当前操作是基本设计,BackgroundWorker自然有很好的支持:
_demoBGWorker。workers upports cancellation=true;
与WorkerReportsProgress属性一样,如果我们希望支持取消操作,我们需要将WorkerSupportsCancellation属性设置为true。并且还在BGWorker_DoWork方法中支持,在Thread之后添加代码。在for循环中休眠(600 ):
bgWorker。ReportProgress(i,message);
线程。睡眠(600);
//在操作过程中,需要检查用户是否取消了当前操作。
如果(bgWorker。CancellationPending==true)
{
e.取消=真;
打破;
}
如果检测到用户点击的取消按钮,则退出当前计算过程。以下是当您单击“取消”按钮时要调用的代码:
_demoBGWorker。CancelAsync();
现在已经可以支持取消操作了,赶紧试试吧!
异常处理
计算过程中出现异常怎么办?有什么方法可以知道计算过程已经结束?当然,即使是正常端也需要得到计算结果。
_demoBGWorker。RunWorkerCompleted=BGWorker _ RunWorkerCompleted;
private void BGWorker _ RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
//如果用户取消当前操作,则关闭窗口。
如果(即取消)
{
这个。close();
}
//计算已经结束,需要禁用取消按钮。
this . BTN cancel . enabled=false;
//计算过程中的异常会被捕获,可以在这里处理。
如果(e .错误!=空)
{
type error type=e . error . gettype();
开关(错误类型。姓名)
{
case“ArgumentNullException”:
案例“MyException”:
//做点什么。
打破;
默认值:
//做点什么。
打破;
}
}
//计算结果信息:e .结果
//用它做点什么。
}
DoWork事件处理程序返回后,将调用RunWorkerCompleted事件处理程序。通过它,我们可以在操作之后进行一些操作,比如禁用取消按钮、异常处理、结果显示等。
注意,如果要获取e.Result,需要在BGWorker_DoWork方法中设置e.Result属性,比如:
e.结果=总和;
综上所述,BackgroundWorker类功能完善,简单易用,真的是处理异步耗时操作的利器!
这就是本文的全部内容。希望对大家的学习有帮助,支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。