一个通过BackgroundWorker实现WinForm异步操作的例子
在最近的一个Smart Client项目中,为了演示异步操作的实现,写了一个基于BackgorundWorker的例子。由于这个理基本上实现了BackgorundWorker的大部分功能:异步操作的启动、操作结束后的回调、异步操作的撤销和进度报告等等。尽管没有太多的技术含量,姑且放上来与大家分享。 一、场景描述下面是程序运行时的截图。本程序模拟这样的一个场景:有两组相互独立的数据需要逐条获取和显示,左边和右边两个groupbox分别代表基于这两组数据的操作,由于他们完全独立,因此可以并行执行。当点击Start按钮,以异步的方式从存储介质中逐条获取数据,并将获取的数据追加到对应的ListBox中,ProgressBar真实反映以获取的数据条数和总记录条数的百分比,同时,当前获取的条数也会在下方的Label上随着操作的继续而动态变化。此外通过点击Stop按钮,可以中止掉当前的操作。当操作被中止后,ProgressBar和Label反映中止的那一刻的状态。 二、代码实现由于界面上左右两边是两个互不干扰、相互独立的操作,所以分别创建了两个BackgroundWorker组件来负责(如下图:backgroundWorkerLeft和backgroundWorkerRight)。 将两个BackgroundWorker的WorkerReportsProgress和WorkerSupportsCancellation设为true。 我们假设获取的记录数固定,我们为此定义一个常量: 1: private static int MaxRecords = 100; 下面是左边Start按钮的Click event handler: 2: {
注:这些操作需要操作UI上的控件,只能在Main Thread中进行。如何在RetrieveData方法进行的话,由于该方式是一个异步方法,是会抛出异常的。
4: { 6: } 8: this.backgroundWorkerLeft.RunWorkerAsync(MaxRecords);
10: this.buttonCacnelLeft.Enabled = true; void backgroundWorkerLeft_DoWork(try
catch (Exception ex) 9: MessageBox.Show(ex.Message); 11: } int RetrieveData(BackgroundWorker worker,1)">int maxRecords = (int)e.Argument;
5: for (int i = 1; i <= maxRecords; i++) 7: if (worker.CancellationPending)
9: return i;
11:? 13: worker.ReportProgress(percent,new KeyValuePair<int,1)">string>(i,Guid.NewGuid().ToString())); 15: } 17: return maxRecords;
void backgroundWorkerLeft_ProgressChanged( 3: KeyValuePair<string> record = (KeyValuePair<string>) e.UserState ; this.progressBarLeft.Value = e.ProgressPercentage; 7: } 由于操作的时间可能无法预知,在长时间不能完全获取数据的情况下,用户可以需要手工结束掉当前的操作。这个操作实现在Stop按钮的Click事件中: 4: }
如何操作正常地结束,BackgroundWorker的RunWorkerCompleted会被触发,下面是RunWorkerCompleted
event handler的定义: "Total records: {0}",e.Result);
catch (TargetInvocationException ex) 11: MessageBox.Show(ex.InnerException.GetType().ToString()); 13: } 上面介绍的是界面左边功能的实现,右边部分的实现完全一致。干兴趣的朋友可以参考Source Code. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |