如何使用backgroundworker暂停进行异步操作

【图文】BackgroundWorker组件总结_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
BackgroundWorker组件总结
上传于||文档简介
&&c​#​异​步​模​式​编​程​组​件​详​细​介​绍​-​-​事​件​-​-​方​法​-​-​属​性
大小:89.50KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢C# 使用BackgroundWorker实现WinForm异步
来源:博客园
写了一个基于BackgorundWorker演示异步操作的例子。由于这个理基本上实现了BackgorundWorker的大部分功能:异步操作的启动、操作结束后的回调、异步操作的撤销和进度报告等等。尽管没有太多的技术含量,姑且放上来与大家分享。
1、场景描述
下面是程序运行时的截图。本程序模拟这样的一个场景:有两组相互独立的数据需要逐条获取和显示,当点击Start按钮,以异步的方式从存储介质中逐条获取数据,并将获取的数据追加到对应的ListBox中,ProgressBar真实反映以获取的数据条数和总记录条数的百分比,同时,当前获取的条数也会在下方的Label上随着操作的继续而动态变化。此外通过点击Stop按钮,可以中止掉当前的操作。当操作被中止后,ProgressBar和Label反映中止的那一刻的状态。
 
2、代码实现
由于界面上两个互不干扰、相互独立的操作,所以分别创建了BackgroundWorker组件来负责。
 
将BackgroundWorker的WorkerReportsProgress和WorkerSupportsCancellation设为true。
 
我们假设获取的记录数固定,我们为此定义一个常量:
private static int MaxRecords = 100;
下面是Start按钮的Click event handler:
当Start按钮被点击后,RunWorkerAsync方法被掉调用,我们定义的常量(MaxRecords )当作参数被掺入。随后,将会触发其DoWork事件,Dowork event handler处理代码如下:


 1 private void btnStart_Click(object sender, EventArgs e)
 2
if (this.backgroundWorker1.IsBusy)
 4
return;
 6
}
 7 
 8
this.listBox1.Items.Clear();
 9
this.backgroundWorker1.RunWorkerAsync(maxRecords);
10
this.btnStart.Enabled = false;
11
this.btnCancle.Enabled = true;
12
}


private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
e.Result=this.RetrieveData(this.backgroundWorker1,e);
catch(Exception ex)
MessageBox.Show(ex.Message);
 
}


调用RetrieveData方法逐条获取数据。注意该方法的两个参数:

BackgroundWorker和DoWorkEventArgs 对象,返回值是返回数据的数量。由于在Start_Click中,我们将常量MaxRecords 作为参数传入了BackgroundWorker的RunWorkerAsync方法, 此时的e.Argument = MaxRecords。之所以要将这两个参数传入RetrieveData()方法,是因为该方法是为两个BackgroundWorker服务的,需要通过参数来区别当前是哪个BackgroundWorker。我们再来看看RetrieveData方法的定义:
 

 1
private int RetrieveData(BackgroundWorker backgroundWorker, DoWorkEventArgs e)
 2
int SumRecords = (int)e.A
 4
int pecent = 0;
 5
for (int i = 0; i & SumR i++)
 6
if (backgroundWorker.CancellationPending)
 8
return
 9
pecent = (int)((double)i / (double)SumRecords * 100);
10
backgroundWorker.ReportProgress(pecent, new KeyValuePair&int, string&(i, Guid.NewGuid().ToString()));
11
Thread.Sleep(1000);
12
return SumR
15
}

 
通过e.Argument,获得最大数据获取量之后,进行一个for循环,在每次迭代中,如何worker.CancellationPending==true,代表异步操作被显示取消,则直接返回;否则,调用BackgroundWorker的ReportProgress方法。ReportProgress具有两个重载:
public void ReportProgress(int percentProgress);
public void ReportProgress(int percentProgress, object userState);
percentProgress代表当前进度,从0-100。userState便于传入一些额外的参数。在界面上,由于数据的当前数量需要实时地显示,而记录也是现取现加(取出一条就在ListBox上追加)。所以制定一个KeyValuePair&int,string&对象作为第二个参数。其中Key为当前记录数,Value是一个Guid,代表取出的数据。
ReportProgress的调用将会导致ProgressChanged事件被触发。ProgressChanged event handler用于显示当前进度、当前记录数量和显示获取的纪录:
 

 1 private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
 2
KeyValuePair&int, string& record = (KeyValuePair&int, string&)e.UserS
 4 
 5
this.lblProcess.Text =
 6 
 7
string.Format("There are {0} records retrieved!", record.Key);
 8 
 9 
10 
11
this.progressBar1.Value = e.ProgressP
12 
13
this.listBox1.Items.Add(record.Value);
14
}

 
注:这些操作需要操作UI上的控件,只能在Main Thread中进行。如何在
RetrieveData方法进行的话,由于该方式是一个异步方法,是会抛出异常的。
由于操作的时间可能无法预知,在长时间不能完全获取数据的情况下,用户可以需要手工结束掉当前的操作。这个操作实现在Stop按钮的Click事件中:
如何操作正常地结束,BackgroundWorker的RunWorkerCompleted会被触发,
下面是RunWorkerCompleted
 
 

 1 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 2
try
 4
{
 5 
 6
this.lblProcess.Text = string.Format("Total records: {0}", e.Result);
 7 
 8
this.btnStart.Enabled = true;
 9
this.btnCancle.Enabled = false;
10 
11
}
12 
13
catch (TargetInvocationException ex)
14
{
15 
16
MessageBox.Show(ex.InnerException.GetType().ToString());
17 
18
}

 
event handler的定义:
上面介绍的是功能的实现.
 源代码下载地址:
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动BackgroundWorker组件实现异步操作详解 -
& & & BackgroundWorker组件
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 当后台操作已完成、被取消或引发异常时发生
另外还有三个重要的参数是RunWorkerCompletedEventArgs以及DoWorkEventArgs、ProgressChangedEventArgs。
BackgroundWorker的各属性、方法、事件的调用机制和顺序:
从上图可见在整个生活周期内发生了3次重要的参数传递过程:
参数传递1:此次的参数传递是将RunWorkerAsync(Object)中的Object传递到DoWork事件的 DoWorkEventArgs.Argument,由于在这里只有一个参数可以传递,所以在实际应用往封装一个类,将整个实例化的类作为 RunWorkerAsync的Object传递到DoWorkEventArgs.Argument(向后台线程中传递必要的参数)。
参数传递2:此次是将程序运行进度传递给ProgressChanged事件,在UI线程中更新界面显示的后台线程处理的进度信息。
参数传递3:在DoWork事件结束之前,将后台线程产生的结果数据赋给DoWorkEventArgs.Result同时RunWorkerCompleted事件中调用RunWorkerCompletedEventArgs.Result属性取得后台线程产生的结果。温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(3867)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
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 的文章

 

随机推荐