如何使用wpf backgroundworkerr进行异步操作

君,已阅读到文档的结尾了呢~~
异步处理form假死(BackgroundWorker类详细用法)
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
异步处理form假死(BackgroundWorker类详细用法)
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(3780)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'BackgroundWorker类详细用法',
blogAbstract:'统计某个磁盘分区的文件夹或者文件数目,如果分区很大或者文件过多的话,处理不好就会造成“假死”的情况,或者报“线程间操作无效”的异常,为了解决这个问题,可以使用委托来处理,在.net2.0中还可以用BackgroundWorker类。BackgroundWorker类是.net 2.0里新增加的一个类,对于需要长时间操作而不需要用户长时间等待的情况可以使用这个类。&注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。&',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:9,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:2,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}使用BackgroundWorker组件进行异步操作编程 - viper2010 - 博客园
在应用程序中,可能会遇到一些执行耗时的功能操作,比如数据下载、复杂计算及数据库事务等,一般这样的功能会在单独的线程上实现,执行结束后结果显示到用户界面上,这样可避免造成用户界面长时间无响应情况。在.NET 2.0及以后的版本中,FCL提供了BackgroundWorker组件来方便的实现这些功能要求。
BackgroundWorker类位于ponentModel 命名空间中,通过该类在单独的线程上执行操作实现基于事件的异步模式。下面对BackgroundWorker类的主要成员进行介绍。
BackgroundWorker类的第1个主要方法是RunWorkerAsync,该方法提交一个以异步方式启动运行操作的请求,发出请求后,将引发 DoWork 事件,在事件处理程序中开始执行异步操作代码。RunWorkerAsync 方法签名如下,
publicvoidRunWorkerAsync();
publicvoidRunWorkerAsync(Object&argument);
如果异步操作需要操作参数,可以将其作为argument参数提供,由于参数类型为Object,因此访问时可能需要进行类型转换。
CancelAsync&方法提交终止异步操作的请求,并将 CancellationPending 属性设置为 true。需要注意的是,CancelAsync 方法是否调用成功,同WorkerSupportsCancellation 属性相关,如果允许取消执行的异步操作,需将WorkerSupportsCancellation 属性设置为true,否则调用该方法将抛出异常。CancelAsync方法不含参数,方法签名如下,
publicvoid&CancelAsync();
调用 CancelAsync 方法时,BackgroundWorker的 CancellationPending 属性值将被设置为true,因此在编写单独线程中执行的辅助方法时,代码中应定期检查 CancellationPending 属性,查看是否已将该属性设置为 true,如果为true,应该结束辅助方法的执行。有一点需要注意的是,DoWork 事件处理程序中的代码有可能在发出取消请求时已经完成处理工作,因此,DoWork事件处理程序或辅助方法可能会错过设置CancellationPending属性为true的时机。在这种情况下,即使调用 CancelAsync方法发出了取消异步操作请求,RunWorkerCompleted 事件处理程序中RunWorkerCompletedEventArgs 参数的 Cancelled 标志也不会被设置为 true,这是在多线程编程中经常会出现的竞争条件问题,因此编写代码的时候需要考虑。
在执行异步操作时,如果需要跟踪异步操作执行进度,BackgroundWorker类提供了 ReportProgress 方法,调用该方法将引发 ProgressChanged 事件,通过注册该事件在事件处理程序中获取异步执行进度信息。方法签名如下:
publicvoidReportProgress(int&percentProgress);
publicvoidReportProgress(int&percentProgress,Object&userState);
该方法包含两个版本,percentProgress表示进度百分比,取值为0-100,userState为可选参数表示自定义用户状态。
同CancelAsync 方法一样,BackgroundWorker的WorkerReportsProgress 属性设置为 true时,ReportProgress 方法才会调用成功,否则将引发InvalidOperationException异常。
上面已经提到了BackgroundWorker的3个属性,CancellationPending用来提示操作是否已经取消,WorkerReportsProgress和WorkerSupportsCancellation分别用来设置是否允许进度汇报和进行取消操作。
publicboolCancellationPending&{ }
publicboolWorkerReportsProgress&{ }
publicboolWorkerSupportsCancellation&{ }
另外一个会用到的属性是IsBusy,
publicbool&IsBusy { }
通过该属性查询BackgroundWorker实例是否正在运行异步操作,如果 BackgroundWorker 正在运行异步操作,则为true,否则为false。
BackgroundWorker类包含3个事件,在事件处理程序中可进行异步操作辅助代码编写和同用户界面信息交互。
publiceventDoWorkEventHandler&DoW
publiceventProgressChangedEventHandler&ProgressC
publiceventRunWorkerCompletedEventHandler&RunWorkerC
DoWork事件处理程序用来调用辅助方法进行实际处理操作,由于该事件处理程序在不同于UI的线程上执行,因此需要确保在 DoWork 事件处理程序中不操作任何用户界面对象。如果辅助方法需要参数支持,可以通过RunWorkerAsync方法传入,在 DoWork 事件处理程序中,通过 DoWorkEventArgs.Argument 属性提取该参数。在异步操作期间,可以通过 ProgressChanged事件处理程序获取异步操作进度信息,通过RunWorkerCompleted 事件处理程序获取异步操作结果信息,在ProgressChanged和RunWorkerCompleted的事件处理程序中可以安全的同用户界面进行通信。
下面通过一个简单的示例来演示BackgroundWorker组件的典型应用。在本示例中,实现一个数值的求和操作,该操作本身运行很快,为模拟处理过程有一个可感知的时间段,在辅助方法中调用了Thread.Sleep方法。
示例程序通过Windows Forms展示,显示了对1-100的数值进行求和操作,界面如下,
图1:应用程序界面
下面对主要实现代码进行说明,先看一下BackgroundWorker类的初始化,在初始化过程中注册了3个事件,允许异步辅助方法调用,以及异步操作进度通知和操作取消。
private&</ponentModel.BackgroundWorker&backgroundWorker1;
private&void&InitializeBackgoundWorker()
this.backgroundWorker1 =&new&</ponentModel.BackgroundWorker();
&&&&this.backgroundWorker1.WorkerReportsProgress =&true;
&&&&this.backgroundWorker1.WorkerSupportsCancellation =&true;
&&&&this.backgroundWorker1.DoWork +=&new&DoWorkEventHandler(backgroundWorker1_DoWork);
&&&&this.backgroundWorker1.ProgressChanged +=&new&ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
&&&&this.backgroundWorker1.RunWorkerCompleted +=&new&RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
通过StartAsync按钮事件处理程序开始异步处理操作请求,事件处理程序如下,
private&void&startAsyncButton_Click(object&sender,&EventArgs&e)
&&& resultLabel.Text =&String.E
&&&&this.numericUpDown1.Enabled =&false;
&&&&this.startAsyncButton.Enabled =&false;
&&&&this.cancelAsyncButton.Enabled =&true;
&&&&//获取计算数值.
&&&&int&numberToCompute = (int)numericUpDown1.V
&&&&//启动异步操作.
&&& backgroundWorker1.RunWorkerAsync(numberToCompute);
startAsyncButton_Click处理程序首先对一些界面控件进行状态设置,然后调用BackgroundWorker实例的RunWorkerAsync方法开始执行异步操作,而此时就会触发DoWork事件。
void&backgroundWorker1_DoWork(object&sender,&DoWorkEventArgs&e)
&&&&BackgroundWorker&worker = sender&as&BackgroundWorker;
e.Result = ComputeAdd((int)e.Argument, worker, e);
在DoWork事件处理程序中,通过DoWorkEventArgs.Argument属性获取传入的参数传递给ComputeAdd辅助方法,并把处理结果保存到DoWorkEventArgs.Result属性中,最后在RunWorkerCompleted 事件处理程序的RunWorkerCompletedEventArgs.Result 属性中获取处理结果。如果在DoWork事件处理程序中出现异常,则 BackgroundWorker 将捕获该异常并将其传递到 RunWorkerCompleted 事件处理程序,在该事件处理程序中,异常信息作为 RunWorkerCompletedEventArgs 的 Error 属性公开。
private&long&ComputeAdd(int&n,&BackgroundWorker&worker,&DoWorkEventArgs&e)
&&&&long&result = 0;
&&&&for&(int&i = 1; i &= i++)
&&&&&&&&if&(worker.CancellationPending)
&&&&&&&&&&& e.Cancel =&true;
&&&&&&&&&&&&break;
&&&&&&&&else
&&&&&&&&&&& result +=
&&&&&&&&&&&&Thread.Sleep(500);
&&&&&&&&&&&&int&percentComplete = (int)((float)i / (float)n * 100);
&&&&&&&&&&& worker.ReportProgress(percentComplete);
&&&&return&
在辅助方法中,代码定期访问BackgroundWorker实例的CancellationPending属性,如果调用了BackgroundWorker的CancelAsync 方法,那么CancellationPending属性值就会被设置为true,辅助方法就结束执行。另外,在辅助方法中实现了进度汇报功能,通过调用worker.ReportProgress方法触发ProgressChanged事件,接着通过ProgressChanged事件处理程序来更新进度显示。
void&backgroundWorker1_ProgressChanged(object&sender,&ProgressChangedEventArgs&e)
&&&&this.progressBar1.Value = e.ProgressP
最后,在RunWorkerCompleted事件处理程序中可以得到异步处理结果信息,分析异步操作是正常执行结束还是在处理中被取消或者是执行出现错误异常而终止。对于处理结果信息的访问有一个标准的顺序,先是判断异步处理是否异常结束,接着判断是否执行了取消操作,最后访问处理结果。
void&backgroundWorker1_RunWorkerCompleted(object&sender,&RunWorkerCompletedEventArgs&e)
&&&&if&(e.Error !=&null)
&&&&&&&&MessageBox.Show(e.Error.Message);
&&&&else&if&(e.Cancelled)
&&&&&&& resultLabel.Text =&"Canceled";
&&&&&&& resultLabel.Text = e.Result.ToString();
this.numericUpDown1.Enabled =&true;
&&& startAsyncButton.Enabled =&true;
&&& cancelAsyncButton.Enabled =&false;
上面的例子是在单个窗口中完成所有功能,可以对其进行简单的修改实现在独立对话框中显示进度并提供取消操作的功能。
图2:进度显示对话框
新建一个窗体命名为ProcessForm用来显示异步操作进度,对ProcessForm类的默认构造函数进行修改,传入BackgroundWorker实例的引用,注册ProgressChanged事件实现窗体进度条的更新,注册RunWorkerCompleted事件通知ProcessForm窗体关闭。
public&ProcessForm(BackgroundWorker&backgroundWorker1)
&&& InitializeComponent();
&&&&this.backgroundWorker1 = backgroundWorker1;
&&&&this.backgroundWorker1.ProgressChanged +=&new&ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
&&&&this.backgroundWorker1.RunWorkerCompleted +=&new&RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
void&backgroundWorker1_RunWorkerCompleted(object&sender,&RunWorkerCompletedEventArgs&e)
&&&&this.Close();
void&backgroundWorker1_ProgressChanged(object&sender,&ProgressChangedEventArgs&e)
&&&&this.progressBar1.Value = e.ProgressP
private&void&cancelButton1_Click(object&sender,&EventArgs&e)
&&&&this.backgroundWorker1.CancelAsync();
&&&&this.cancelButton1.Enabled =&false;
&&&&this.Close();
对于进度窗口的显示方式可以是模式窗口或非模式窗口,两者的实现代码并没有太大区别,改进后的StartAsync按钮事件处理程序如下。
private&void&startAsyncButton_Click(object&sender,&EventArgs&e)
&&&&// ...
&&& backgroundWorker1.RunWorkerAsync(numberToCompute);
&&&&ProcessForm&form =&new&ProcessForm(this.backgroundWorker1);
&&& form.ShowDialog(this);//模式
&&&&//form.Show(this);//非模式
在分析BackgroundWorker实现原理之前,需要了解一下在.NET Framework 2.0版本中新增加的两个类。AsyncOperationManager 类和AsyncOperation 类都位于ponentModel 命名空间中,AsyncOperation类提供了对异步操作的生存期进行跟踪的功能,包括操作进度通知和操作完成通知,并确保在正确的线程或上下文中调用客户端的事件处理程序。
publicvoidPost(SendOrPostCallback&d,Object&arg);
publicvoidPostOperationCompleted(SendOrPostCallback&d,Object&arg);
通过在异步辅助代码中调用Post方法把进度和中间结果报告给用户,如果是取消异步任务或提示异步任务已完成,则通过调用PostOperationCompleted方法结束异步操作的跟踪生命期。在PostOperationCompleted方法调用后,AsyncOperation对象变得不再可用,再次访问将引发异常。在两个方法中都包含SendOrPostCallback委托参数,签名如下,
publicdelegatevoidSendOrPostCallback(Object&state);
SendOrPostCallback&委托用来表示在消息即将被调度到同步上下文时要执行的回调方法。
AsyncOperation类看上去很强大,不过有开发人员反映该类的.NET 2.0版本存在Bug,在3.0及后面的版本微软是否进行过更新还需进一步考证。笔者在控制台应用程序中进行测试,asyncOperation的Post方法递交的SendOrPostCallback委托不一定是在控制台主线程执行,通过访问System.Threading.Thread.CurrentThread.ManagedThreadId可以确认这一点,奇怪的是控制台程序未发现运行异常,这个可能是控制台程序执行方式不同于窗体程序的原因。
AsyncOperationManager&类为AsyncOperation对象的创建提供了便捷方式,通过CreateOperation方法可以创建多个AsyncOperation实例,实现对多个异步操作进行跟踪。
BackgroundWorker组件通过DoWork事件实现了在单独的线程上执行操作,其内部通过异步委托来完成,在BackgroundWorker类内部声明了WorkerThreadStartDelegate委托,并定义了threadStart成员变量,同时在构造函数中初始化threadStart。
private&delegate&void&WorkerThreadStartDelegate(object&argument);
private&readonly&WorkerThreadStartDelegate&threadS
public&BackgroundWorker()
this.threadStart =&new&WorkerThreadStartDelegate(this.WorkerThreadStart);
BackgroundWorker通过调用RunWorkerAsync方法开始执行异步操作请求,并在方法体中调用threadStart.BeginInvoke方法实现异步调用。
public&void&RunWorkerAsync(object&argument)
&&&&if&(this.isRunning)
&&&&&&&&throw&new&InvalidOperationException(SR.GetString("BackgroundWorker_WorkerAlreadyRunning"));
&&&&this.isRunning =&true;
&&&&this.cancellationPending =&false;
&&&&this.asyncOperation =&AsyncOperationManager.CreateOperation(null);
&&&&this.threadStart.BeginInvoke(argument,&null,&null);
在threadStart委托中指定的WorkerThreadStart方法将触发DoWork事件,使用者通过注册DoWork事件执行异步代码的操作,从下面的代码可以看出在DoWork事件处理程序中不能访问UI元素的原因。
private&void&WorkerThreadStart(object&argument)
&&&&object&result =&null;
&&&&Exception&error =&null;
&&&&bool&cancelled =&false;
&&&&&&&&DoWorkEventArgs&e =&new&DoWorkEventArgs(argument);
&&&&&&&&this.OnDoWork(e);
&&&&&&&&if&(e.Cancel)
&&&&&&&&&&& cancelled =&true;
&&&&&&&&else
&&&&&&&&&&& result = e.R
&&&&catch&(Exception&exception2)
&&&&&&& error = exception2;
&&&&RunWorkerCompletedEventArgs&arg =&new&RunWorkerCompletedEventArgs(result, error, cancelled);
&&&&this.asyncOperation.PostOperationCompleted(this.operationCompleted, arg);
在上述代码中,this.OnDoWork(e)方法产生DoWork事件,DoWork事件处理程序执行完成后会判断在事件处理程序中是否对DoWorkEventArgs.Cancel属性进行了设置,如果使用者调用了CancelAsync 方法那么DoWorkEventArgs.Cancel会被设置为true,事件处理程序正常执行完成时可以从DoWorkEventArgs.Result得到执行结果,如果出现处理异常将扑获异常,所有需要的信息将包含在RunWorkerCompletedEventArgs实例中,最后执行asyncOperation.PostOperationCompleted方法产生RunWorkerCompleted 事件,因此在RunWorkerCompleted事件处理程序中可以获得取消操作、处理异常或处理结果的信息。
类似于RunWorkerCompleted事件的发生机制,对于异步操作进度通知事件发生通过ReportProgress方法实现。
public&void&ReportProgress(int&percentProgress,&object&userState)
&&&&if&(!this.WorkerReportsProgress)
&&&&&&&&throw&new&InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntReportProgress"));
&&&&ProgressChangedEventArgs&arg =&new&ProgressChangedEventArgs(percentProgress, userState);
&&&&if&(this.asyncOperation !=&null)
&&&&&&&&this.asyncOperation.Post(this.progressReporter, arg);
&&&&&&&&this.progressReporter(arg);
调用者在DoWork事件处理程序中通过调用ReportProgress方法进行进度汇报,其内部通过asyncOperation.Post方法产生ProgressChanged 事件,如果asyncOperation为null,那么就调用progressReporter方法产生事件,但是调用progressReporter方法产生事件明显存在问题,因为这样产生的事件所在线程同DoWork事件为同一线程,ProgressChanged事件处理程序也会执行在DoWork线程同一上下文中,因此在ProgressChanged事件处理程序中访问ProgressBar控件将出现&线程间操作无效: 从不是创建控件&progressBar1&的线程访问它。&的异常。笔者认为这样的处理是组件的一个Bug,如果asyncOperation为null,更好的处理方式是抛出异常或不做通知处理。值得一提的是,在控制台应用程序中测试调用progressReporter方法不会出现&线程间操作无效&的异常。
结合构造函数,下面的代码有助于进一步理解ProgressChanged事件和RunWorkerCompleted事件产生机制。
public&BackgroundWorker()
this.threadStart =&new&WorkerThreadStartDelegate(this.WorkerThreadStart);
this.operationCompleted =&new&SendOrPostCallback(this.AsyncOperationCompleted);
&&&&this.progressReporter =&new&SendOrPostCallback(this.ProgressReporter);
private&void&ProgressReporter(object&arg)
&&&&this.OnProgressChanged((ProgressChangedEventArgs)arg);
private&void&AsyncOperationCompleted(object&arg)
&&&&this.isRunning =&false;
&&&&this.cancellationPending =&false;
&&&&this.OnRunWorkerCompleted((RunWorkerCompletedEventArgs)arg);
最后,看一下RunWorkerAsync方法和CancelAsync方法的实现。
public&void&RunWorkerAsync(object&argument)
&&&&if&(this.isRunning)
&&&&&&&&throw&new&InvalidOperationException(SR.GetString("BackgroundWorker_WorkerAlreadyRunning"));
&&&&this.isRunning =&true;
&&&&this.cancellationPending =&false;
&&&&this.asyncOperation =&AsyncOperationManager.CreateOperation(null);
&&&&this.threadStart.BeginInvoke(argument,&null,&null);
public&void&CancelAsync()
&&&&if&(!this.WorkerSupportsCancellation)
&&&&&&&&throw&new&InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntSupportCancellation"));
&&&&this.cancellationPending =&true;
BackgroundWorker组件简化了基于事件的异步操作编程,根据其实现原理可进一步编写支持多任务的异步操作组件来更好的满足异步操作密集的应用开发需求。边学习边分享,纯属抛砖引玉。
线程的一个好处是异步的执行操作,在winform中,很多耗时操作执行时,为优化用户体验,避免长时间等待,从而运用线程技术异步的执行耗时操作,但不会阻塞主线程。
最近系统很多耗时查询导致体验很差,于是想到了用BackGroundWorker异步处理。而且要支持某些耗时达到几十秒的操作,可以取消。
BackGroundWorker有CancelAsync()这个方法。该方法只会将BackGroundWorker的CancellationPending属性设为true,但不会实际终止线程!网上找了些资料,代码如下
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
for (int i = 0; i & 100; i++)
if (backgroundWorker1.CancellationPending)
e.Cancel = true;
即在doWork事件中,不停的循环判断是否执行了取消操作。这种适用于执行多次方法时,而且无法在某个方法执行时将线程取消。如果我doWork事件里,没有for循环,而是一次耗时的数据访问操作,那这样的处理没有任何意义。
于是在下想到,可以在doWork事件里做如下处理
1.异步的去执行耗时操作。
2.while监视异步耗时操作是否完成,只要未完成就一直循环。循环内部判断是否执行了取消操作。如果执行了取消操作,则终止线程。代码如下
private delegate int LongTimeDele();
private bool isComplated=false;
private int result=0;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
this.BeginInvoke(new LongTimeDele(()=&{
Thread.Sleep(10000);////模拟耗时
for (int i = 0; i & 100; i++)
isComplated=true;
while(!isComplated){
if (backgroundWorker1.CancellationPending)
e.Cancel = true;
试验之后,不知何故在this.BeginInvoke中的循环会阻塞主线程! 即界面卡主不动了,BeginInvoke应该是一步执行的,在下功力尚浅,不知何故,还请高手指教。
于是想到了异步委托。直接上代码
public partial class BackgroundWorkerTest : Form
public BackgroundWorkerTest()
InitializeComponent();
/// &summary&
/// 建立一个委托,用来调用耗时操作。返回值是int,当然也可以是string、DataTable.....
/// &/summary&
/// &returns&&/returns&
private delegate int LongTimeDele();
/// &summary&
/// doWork事件
/// &/summary&
/// &param name="sender"&&/param&
/// &param name="e"&&/param&
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
//声明一个委托的实例
var waitHandller = new LongTimeDele(
//线程休眠10秒,模拟耗时操作
Thread.Sleep(10000);
var sumResult = 0;
for (int i = 0; i & 100; i++)
sumResult++;
return sumR
//BeginInvoke,异步的去执行委托实例里的匿名方法。该方法返回的是一个IAsyncResult。返回值的状态会实时更新!
var isa = waitHandller.BeginInvoke(null, null);
//由于上面是异步,所以while的代码不会等待上面操作完成后执行,二者几乎同时执行
//判断isa是否完成了,未完成的话(等待耗时操作)执行内部代码
while (!isa.IsCompleted)
//判断CancellationPending属性是否为true。如果你点击了取消button,这个属性就变成true了
if (backgroundWorker1.CancellationPending)
//取消操作
e.Cancel = true;
//能执行到这里就说明操作完成了,把结果放进e中,传递给RunWorkerCompleted事件
e.Result = waitHandller.EndInvoke(isa);
/// &summary&
/// backgroundWorker执行完毕时事件,无论正常完成还是取消都会出发该事件
/// &/summary&
/// &param name="sender"&&/param&
/// &param name="e"&&/param&
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
//只要不是类型EventArgs,你想要的数据e里面应有尽有!判断是否取消了操作
if (e.Cancelled)
MessageBox.Show("操作已取消");
//否则显示结果
MessageBox.Show(e.Result.ToString());
/// &summary&
/// 取消按钮事件
/// &/summary&
/// &param name="sender"&&/param&
/// &param name="e"&&/param&
private void btnCancle_Click(object sender, EventArgs e)
backgroundWorker的CancelAsync()方法,该方法只会将CancellationPending属性设为true,并不会实际结束线程执行
backgroundWorker1.CancelAsync();
/// &summary&
/// 开始按钮事件
/// &/summary&
/// &param name="sender"&&/param&
/// &param name="e"&&/param&
private void btnStart_Click(object sender, EventArgs e)
//判断线程是否繁忙
if (backgroundWorker1.IsBusy)
MessageBox.Show("系统繁忙");
//空闲开始异步操作
backgroundWorker1.RunWorkerAsync();
阅读(...) 评论()

我要回帖

更多关于 backgroundworker 的文章

 

随机推荐