zoukankan      html  css  js  c++  java
  • 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()。代码如下:

    1private 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就是为此来做前提。代码如下:

    1private 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,有话不到位的还请兄弟们多指教!

  • 相关阅读:
    【Demo 0011】多媒体播放器
    【Demo 0010】事件响应链
    【Demo 0009】表视图控制器
    【Demo 0008】标签控制器
    【Demo 0007】导航控制器
    【Demo 0006】iOS常用控件
    【Demo 0005】视图控制器
    【Demo 0004】屏幕、窗体及视图基础知识
    2019.7.16考试反思
    内网 可怜与超市题解 树形dp+合并
  • 原文地址:https://www.cnblogs.com/quluqi/p/1607318.html
Copyright © 2011-2022 走看看