博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 使用BackgroundWorker实现WinForm异步
阅读量:5304 次
发布时间:2019-06-14

本文共 4132 字,大约阅读时间需要 13 分钟。

写了一个基于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         { 3             if (this.backgroundWorker1.IsBusy) 4             { 5                 return; 6             } 7  8             this.listBox1.Items.Clear(); 9             this.backgroundWorker1.RunWorkerAsync(maxRecords);10             this.btnStart.Enabled = false;11             this.btnCancle.Enabled = true;12         }
1
2
3
4
5
6
7
8
9
10
11
12
private
void
backgroundWorker1_DoWork(
object
sender, DoWorkEventArgs e)
        
{
            
try
            
{
                
e.Result=
this
.RetrieveData(
this
.backgroundWorker1,e);
            
}
            
catch
(Exception ex)
            
{
                
MessageBox.Show(ex.Message);
                
throw
;
            
}
        
}

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

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

 

1  private int RetrieveData(BackgroundWorker backgroundWorker, DoWorkEventArgs e) 2         { 3             int SumRecords = (int)e.Argument; 4             int pecent = 0; 5             for (int i = 0; i < SumRecords; i++) 6             { 7                 if (backgroundWorker.CancellationPending) 8                     return i; 9                 pecent = (int)((double)i / (double)SumRecords * 100);10                 backgroundWorker.ReportProgress(pecent, new KeyValuePair
(i, Guid.NewGuid().ToString()));11 Thread.Sleep(1000);12 13 }14 return SumRecords;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         { 3             KeyValuePair
record = (KeyValuePair
)e.UserState; 4 5 this.lblProcess.Text = 6 7 string.Format("There are {0} records retrieved!", record.Key); 8 9 10 11 this.progressBar1.Value = e.ProgressPercentage;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         { 3             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             }19         }

 

event handler的定义:

上面介绍的是功能的实现.

 源代码下载地址:
 
 

转载于:https://www.cnblogs.com/amylis_chen/p/3436257.html

你可能感兴趣的文章
在MyEclipse下统计工程的代码(package、行数、类个数)
查看>>
Erlcron分析学习
查看>>
idea 快捷键
查看>>
菜鸟运维笔记:Windows上用Xshell管理你的云主机
查看>>
JavaScript中的this
查看>>
jsp
查看>>
03 基本数据结构 - 栈
查看>>
Hyper-V虚拟机上安装一个图形界面的Linux系统
查看>>
微信小程序之随笔
查看>>
ios蓝牙详解
查看>>
React Native在Android平台运行gif的解决方法转载
查看>>
Mybatis RowBounds 是逻辑分页
查看>>
hdu 3341(ac自动机+状态压缩)
查看>>
51单片机之蓝牙遥控小车_效果展示+单片机知识+完整蓝牙电车代码
查看>>
Sql Server中REPLACE函数的使用
查看>>
SqlServerl的行转列
查看>>
JavaScript跨域总结与解决办法
查看>>
Hover功能
查看>>
[LeetCode] Jump Game II
查看>>
js千分位处理
查看>>