C#多线程浅接触一、
闲暇时间,考虑着怎样提高系统软件系统性能,特别是win程序,除了对象的生命周期的管理之外,想到了使用多线程,翻开书看了下,在此写下自己的学习过程。
大家都知道,在开发win中,窗体控件是在一个线程中创建,所以如果在程序中使用多线程,在非创建控件线程中是不可以直接对控件进行处理的,只能是通过Invoke(),BeginInvoke(),EndInvoke()以及属性InvokeRequired来进行处理,所以在此可以使用委托来实现,但在win基于事件开发中提供了BackgroundWorker类,它封装好了这线程的整个生命周期的处理及访问过程,开始还感觉挺麻烦,不过细看一下处理过程还挺清晰,下面就通过小例子对此方法进行说明。
在使用BackgroundWorker类前,先说下,一个新线程的生命周期包括下面几个方面(自己的话来概括),首先要先初始化这个线程,在类中是通过调用RunWorkerAsync()方法来触发DoWork()事件的,当然可以进行传值。线程启动后,如果要使线程正常工作,还要确保WorkerReportsProgress属性为true,这样就可以正常使用ProgressChanged()事件了,当线程处理完或是中断后会触发RunWorkerCompleted()事件,在这两个处理方法中可以对窗体控件进行直接访问(省了好多),上面说到中断线程,为了提供此功能,还要确保WorkerSupportsCancellation属性为true,若触发CancelAsync()方法,就可对线程进行中断,当然,线程中断后同样会调用RunWorkerCompleted()方法来进行处理。下面就以例子来说明一下。界面如下:
此例为处理一进度条(俗、易懂),点击Start按钮时进度条会显示进度,此时Start按钮变为不可用,当缓慢的处理过程(此处为进度条)结束后,会把两个文件框中的文本(数字)相加结果显示在lable1中,当在处理过程中点击Cancel按钮,线程就会中止,lable1显示为中止字样。
因为在传值过程中为object,所以现在实现了简单的结构类型来封装所需的数据(在此为两个文本内容),简单如下:
2 {
3 public int x;
4 public int y;
5
6 public input(int x, int y)
7 {
8 this.x = x;
9 this.y = y;
10 }
11 }
看下Start按钮的事件处理,在此会触发线程开启事件DoWork()。代码如下:
2 {
3 this.button1.Enabled = false;
4 this.progressBar1.Value = 0;
5 backgroundWorker1.RunWorkerAsync(
6 new input(int.Parse(textBox1.Text), int.Parse(textBox2.Text)));
7 }
在此控制了按钮以及进度条的状态,并实现了带参数的重载方法RunWorkerAsync(object target),将上面的结构传入线程。此时事件DoWork()方法会被触发,事件处理代码如下:
2 {
3 input put = (input)e.Argument;
4 for (int i = 0; i <= 9; i++)
5 {
6 Thread.Sleep(1000);
7 backgroundWorker1.ReportProgress(i * 10);
8 if (backgroundWorker1.CancellationPending)
9 {
10 e.Cancel = true;
11 return;
12 }
13 }
14 e.Result = put.x + put.y;
15 }
可以看到,方法参数中可通过e.Argument来获取传递的参数并进行类型转换,在此方法体中来处理线程要进行的主要工作,可以看到backgroundWorker1.ReportProgress(i * 10);此方法调用就是来触发进度条更新,上面提到WorkerReportsProgress属性为true就是为此来做前提。代码如下:
2 {
3 this.progressBar1.Value = e.ProgressPercentage;
4 }
在此方法中对进度条的状态进行了设置。
在上面主方法体中对backgroundWorker1.CancellationPending属性进行判断,是为了标识线程状态,一旦线程在过程中中断就把Cancel属性设为true,并结束处理过程,感觉这里非常重要!最后当线程处理完工作后可以给object类型的Result属性设置值,也就是为RunWorkerCompleted()方法提供参数。此方法为线程结束(自动和人为都会触发)时触发的,可以在此对程序数据及窗体做最后的处理工作,在此代码如下。
2 {
3 if (e.Cancelled)
4 {
5 this.Lable1.Text = "已经取消";
6 this.progressBar1.Value = 0;
7 }
8 else
9 {
10 this.Lable1.Text = e.Result.ToString();
11 this.progressBar1.Value = 100;
12 }
13
14 this.button1.Enabled = true;
15 }
在此,判断了事件结束的状态,如果是正常结束就显示最后状态,如果是中断就显示为取消字样。
小例子就结束了,最大的好处就是不用太费脑袋去考虑善后工作以及整个的过程,三个主要方法就做好了所有的处理。
刚开始接触win,有话不到位的还请兄弟们多指教!
作者:屈鲁奇
出处:https://www.cnblogs.com/quluqi
联系:496195435@qq.com QQ:496195435
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步