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,所以现在实现了简单的结构类型来封装所需的数据(在此为两个文本内容),简单如下:

 1      public   struct  input
 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()。代码如下:

 

1 private   void  button1_Click( object  sender, EventArgs e)
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()方法会被触发,事件处理代码如下:

 

 1          private   void  backgroundWorker1_DoWork( object  sender, DoWorkEventArgs e)
 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就是为此来做前提。代码如下:

 

1 private   void  backgroundWorker1_ProgressChanged( object  sender, ProgressChangedEventArgs e)
2          {
3            this.progressBar1.Value = e.ProgressPercentage;
4        }

 

在此方法中对进度条的状态进行了设置。

在上面主方法体中对backgroundWorker1.CancellationPending属性进行判断,是为了标识线程状态,一旦线程在过程中中断就把Cancel属性设为true,并结束处理过程,感觉这里非常重要!最后当线程处理完工作后可以给object类型的Result属性设置值,也就是为RunWorkerCompleted()方法提供参数。此方法为线程结束(自动和人为都会触发)时触发的,可以在此对程序数据及窗体做最后的处理工作,在此代码如下。

 

 1   private   void  backgroundWorker1_RunWorkerCompleted( object  sender, RunWorkerCompletedEventArgs e)
 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,有话不到位的还请兄弟们多指教!

你可能感兴趣的:(多线程)