zoukankan      html  css  js  c++  java
  • 多线程:C#.NET中使用BackgroundWorker在模态对话框中显示进度条

      我们使用C#.NET编写WinForm程序时,有时候为了实现在模态对话框中实时显示后台操作的进度,这个时候需要借助于多线程操作在子窗体中显示进度条状态,在父窗体中进行后台操作。你可以在Thread类中自己创建两个线程以完成这个操作,不过C#.NET提供了BackgroundWorker对象可以帮助我们非常方便地来实现这个过程。有关Backgroundworker对象的时候我在“C#遍历文件读取Word内容以及实用BackgroundWoker对象打造平滑进度条”一文中有过介绍,大家可以去看看。

      这里是一个示例,其中展示了如何使用Backgroundworker对象在模态对话框中显示后台操作的实时进度条。

      首先是主窗体代码:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Drawing;
     6 using System.Linq;
     7 using System.Text;
     8 using System.Windows.Forms;
     9 using System.Threading;
    10 
    11 namespace ModalProgressDialog
    12 {
    13     public partial class Form1 : Form
    14     {
    15         protected BackgroundWorker worker = new BackgroundWorker();
    16         protected Form2 frm = new Form2();
    17 
    18         public Form1()
    19         {
    20             worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    21             worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
    22             worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    23 
    24             InitializeComponent();
    25         }
    26 
    27         private void button1_Click(object sender, EventArgs e)
    28         {
    29             worker.WorkerReportsProgress = true;            
    30             worker.RunWorkerAsync();
    31             frm.ShowDialog();
    32         }
    33 
    34         void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    35         {
    36             frm.Close();
    37             MessageBox.Show("Done");
    38         }
    39 
    40         void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    41         {
    42             frm.ProgressValue = e.ProgressPercentage;
    43         }
    44 
    45         void worker_DoWork(object sender, DoWorkEventArgs e)
    46         {
    47             CountTheTime();
    48         }
    49 
    50         private void CountTheTime()
    51         {
    52             int initialValue = 100
    53             for (int count = 0; count < initialValue; count = count + 2
    54             { 
    55                 Thread.Sleep(1000);
    56                 worker.ReportProgress(count); 
    57             }
    58         }
    59     }
    60 }

      主窗体中只有一个按钮,当被点击时,会由BackgroundWorker对象以异步的方式去执行一个假象的后台操作CountTheTime方法。CountTheTime方法从0到100以步长为2每隔1秒更新一下进度条状态,因此这个假象的后台操作大约会持续50秒左右的时间。当程序执行时,进度条指示窗口以模态对话框的形式被弹出,然后实时显示后台操作的进度。

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

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

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

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

      另外还有一个非常重要的属性WorkerReportsProgress - 如果想让BackgroundWorker对象以异步的方式报告线程实时进度,必须将该属性的值设为true。

      BackgroundWorker对象的ReportProgress方法用于向主线程返回后台线程执行的实时进度。

      下面是子窗体的代码:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Drawing;
     6 using System.Linq;
     7 using System.Text;
     8 using System.Windows.Forms;
     9 
    10 namespace ModalProgressDialog
    11 {
    12     public partial class Form2 : Form
    13     {
    14         public int ProgressValue 
    15         {
    16             get { return this.progressBar1.Value; }
    17             set { progressBar1.Value = value; }
    18         }
    19 
    20         public Form2()
    21         {
    22             InitializeComponent();
    23         }
    24     }
    25 }

      子窗体中放置了一个ProgressBar控件,对外可以通过ProgressValue属性来获取和修改进度条的当前值。同时,我们可以将子窗体的FormBorderStyle属性设为FixedDialog以使其看起来更像对话框,然后将MaximizeBoxMinimizeBox都设为false,将ControlBox属性设为false以隐藏窗体关闭按钮。在父窗体中,我们通过BackgroundWorker对象的RunWorkerAsync方法触发DoWork事件,此时CountTheTime()方法被执行。在CountTheTime()方法中,通过ReportProgress()方法从后台进程(父窗体)传递进度指示到主UI线程(子窗体)中,这样同时会触发ProgressChanged事件,然后我们在该事件中更新子窗体的进度条状态。下面是程序执行时的截图。

       注意,使用BackgroundWorker时不能在工作线程中访问UI线程部分,即你不能在BackgroundWorker的事件和方法中操作UI,否则会抛跨线程操作无效的异常。常用的方法是在主窗体的构造函数中添加CheckForIllegalCrossThreadCalls = false;语句。或者使用Thread类创建一个单独的线程,然后使用Invoke方法。可以参考下面这些内容:

    http://www.cnblogs.com/chorrysky/archive/2007/02/10/646891.html

    http://blog.csdn.net/marklr/archive/2009/07/10/4338518.aspx

    http://www.cnblogs.com/kingsky/archive/2009/02/18/1353322.html

  • 相关阅读:
    demo12-回到顶部
    demo11-友情链接
    demo10-超链接标签
    demo09-程序员练习
    demo08-图片标签
    demo07-盒子标签
    demo06-字体标签
    demo05-换行标签
    转&nbsp;j2ee&nbsp;.线程池.对象池,连接池
    几种开源Java&nbsp;Web容器线程池…
  • 原文地址:https://www.cnblogs.com/jaxu/p/2045702.html
Copyright © 2011-2022 走看看