zoukankan      html  css  js  c++  java
  • 线程实用解析(五)BackgroundWorker和Timer

    上一节讲到在实际的编程中某些任务执行完成时间可能较长,比如打开大文件、连接远程计算机或查询数据库,这个时候可能会导致UI界面发生长时间未响应,如果你需要在执行某些任务的同时,还要进行UI界面的响应,BackgroundWorker是您最好的选择,同时,从VS2005开始也BackgroundWorker组件,这使Backgroundworker使用起来更加的方便。

    下面我会通过一个更新UI界面进度条的例子来向大家逐步的讲解BackgroundWorker类

    首先新建一个Form应用程序,在UI也添加一个按钮和一个进度条processbar

    如图所示:

     

    然后进入.cs页

    先声明一个全局的BackgroundWorker 实例

    Private BackgroundWorker backgroundWorker = new BackgroundWorker();

            private static int sum = 0;//定义一个全局的sum,下边函数计数用

    然后在Buntton_Click(object sender, EventArgs e)

    {

        //DoWork 事件在调用RunWorkerAsync()函数时发生,该事件是在另一个线程里执行的,该线程属于线程池中的一个线程。所以,不能在这个事件中操作UI元素

        backgroundworker.DoWork += new DoWorkEventHandler(backgroundworker_DoWork);

       //触发DoWork事件,同时RunWorkerAsync的参数即为DoWork()函数所需的参数,如果参数过多,可以先将参数封装成类,再进行传递

       backgroundworker.RunWorkerAsync(10);

       //获取或设置一个值,该值指示BackgroundWorker能否报告进度更新,在用于更新进度条等的操作中,需要将该值设置为true  backgroundworker.WorkerReportsProgress = true;

     //在实际使用中往往使用给方法和事件更新进度条或者日志信息,通过ReportProgress()来触发该事件  backgroundworker.ProgressChanged+=new ProgressChangedEventHandler(backgroundworker_ProgressChanged);

      //后台操作结束、或取消、异常等会触发该事件,相当于委托中AsyncCallback事件,该事件是在创建控件的线程中执行的 

    backgroundworker.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(backgroundworker_RunWorkerCompleted);

    }

    //随时的显示更新进度

      void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e)

            {

                progressBar1.Value = e.ProgressPercentage;//随着后台操作的执行,不断的更新进度

            }

    //在后台任务执行完之后,将进程条的设为100

    Void backgroundworker_RunWorkerCompleted(objec tsender, RunWorkerCompletedEventArgs e)

            {

                MessageBox.Show("求和结果为:" + sum+"当前的线程为:"+Thread.CurrentThread.ManagedThreadId);

                progressBar1.Value = 100;

            }

    //该事件中进行耗时的操作,但是不要涉及对UI元素的操作

            void backgroundworker_DoWork(object sender, DoWorkEventArgs e)

            {

              MessageBox.Show("DoWork所在的线程为:" + Thread.CurrentThread.ManagedThreadId+"是否为后台线程:"+Thread.CurrentThread.IsBackground);

                int a = (int)e.Argument;

                for (int i = 1; i <= a; i++)

                {

                    sum += i;

                    Thread.Sleep(500);

    //通过执行该方法,触发ProgressChanged事件,不断的更新processbar的值

                    backgroundworker.ReportProgress(sum);            }

            }

    实验结果如下:

     

    通过以上这个例子,相信你基本已经可以自主的运用BackgroundWorker类了,最后再将BackgroundWorker类进行一个总结:

    BackgroundWorker对象有三个主要的事件:

      DoWork - 当BackgroundWorker对象的多线程操作被执行时触发。

      RunWokerCompleted - 当BackgroundWoker对象的多线程操作完成时触发。

      ProgressChanged - 当BackgroundWorker对象的多线程操作状态改变时触发。

      如果想让BackgroundWorker对象以异步的方式报告线程实时进度,必须将属性WorkerReportsProgress的值设为true。BackgroundWorker对象的ReportProgress方法用于向主线程返回后台线程执行的实时进度。

    关于BackgroundWorker就介绍到这里,下面介绍Timer类

    Timer类

    关于Timer类.NET中有三个Timer,分别是: System.Windows.Forms.TimerSystem.Timers.TimerSystem.Threading.Timer  

    System.Windows.Forms.Timer主要用于依赖于WinForm程序中的窗体,Timer代码直接运行于UI线程中,所以可以操作UI控件。

    System.Timers.Timer可以用在Component 或者一般的类里,该Timer的事件默认执行线程池中一个线程,如果需要让代码执行在某个特定线程中,需要通过设置TimerSynchronizingObject 属性

    System.Threading.Timer,可以在任何多线程环境中使用Timer,该事件也是在线程池中的线程上执行的。

    System.Timers.Timer应用示例:

    先将Form窗体中放置一个Button,将ButtonText属性设为Timer

    Button_Click(object sender, EventArgs e)

            {

    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

                timer.Tick += new EventHandler(timer_Tick);

                timer.Interval = 1000;//设置Interval属性,每隔多少秒就触发Tick事件

                timer.Start();

            }

            void timer_Tick(object sender, EventArgs e)

            {

                button8.Text = DateTime.Now.ToLocalTime().ToString();

            }

    通过System.Windows.Forms.Timer可以很容易的操作Ui界面的控件,比如本例可以通过ButtonText属性来显示当前的时间。

    实验结果如下:

     

    System.Threading.Timer示例:

    Button_Click(object sender, EventArgs e)

            {

    //System.Threading.Timer的构造函数有5个重载,基本上都差不多。第一个参数为一个TimerCallback的委托,第二个参数为委托调用函数所需的参数,如果没有可以设置为null,第三个为调用callback之前的延迟时间,第四个调用callback的时间间隔。

    System.Threading.Timer timer1 = new System.Threading.Timer(new TimerCallback(Count), 10, 5000, 10);

    }

    Private static void Count(object obj)

    {

       Int a=(int)obj;

    For(int i=0;i<a;i++)

    {

     Sum+=1;

    }

    MessageBox.Show("Sum的值:"+sum);

    }

    实验结果:因为每个10毫秒就要触发一个Count事件,所以会一直不停的弹出MessageBoxsum是一个全局变量,所以会不断的累加。

     

     

    关于System.Timers.Timer就不再过多的介绍了,希望有兴趣的朋友下去自己了解。

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    洛谷P2066 机器分配【dp】
    [HNOI2004]打鼹鼠【dp】
    [ZJOI2008][BZOJ1037] 生日聚会Party|动态规划]
    Java中Map<Key, Value>存储结构根据值排序(sort by values)
    LATEX如何写多个条件推导式推出一个结论
    书列荐书 |《黑天鹅&#183;如何应对不可预知的未来》【美】纳西姆 尼古拉斯 塔勒布 著
    Java | Stream流、泛型、多线程 | 整理自用
    书列荐书 |《代码整洁之道》之 类 的设计
    书列荐书 |《认知红利》 谢春霖著
    eclipse集成processing、PApplet、proclipsing 问题
  • 原文地址:https://www.cnblogs.com/Olive116/p/2712788.html
Copyright © 2011-2022 走看看