三种跨线程控件访问方法

1、不安全的方法: 将 Control.CheckForIllegalCrossThreadCalls 设置为false (.net1.0中没有)

2、安全的方法: 异步委托(不要将除了控件访问外其他逻辑代码放到委托的回调方法中)

private void button1_Click(object sender, System.EventArgs e)
{
    //实例化一个线程,并引用线程开始执行时要调用的方法
    //这个方法在线程调用start()方法时启动
    barProgress = new Thread(new ThreadStart(ProgressProc)); //调用线程启动ProgressProc方法
    barProgress.IsBackground = true;
    barProgress.Start();
}
private void ProgressProc()
{
    MethodInvoker mi = new MethodInvoker(UpdateProgress);//MethodInvoker表示一个委托,该委托可以执行托管代码中声明为
    while (true)
    {
        Invoke(mi);
        int sleepTime = this.waitTime;
        Thread.Sleep(sleepTime);
    }
}
private void UpdateProgress()  //实现UpdateProgress
{
    //更新界面
}


3、安全的方法: 就是使用BackgroundWorker来替代你自己创建的线程(.net1.0中没有)

BackgroundWorker是一个在System.ComponentModel命名空间下帮助类,它管理着工作线程。它提供了以下特性:

  • "cancel" 标记,对于给工作线程打信号让它结束而没有使用 Abort的情况
  • 提供报道进度,完成度和退出的标准方案
  • 实现了IComponent接口,允许它参与Visual Studio设计器
  • 在工作线程之上做异常处理
  • 更新Windows Forms控件以应答工作进度或完成度的能力

最后两个特性是相当地有用:意味着你不再需要将try/catch语句块放到你的工作线程中了,并且更新Windows Forms控件不需要调用 Control.Invoke了。

BackgroundWorker使用线程池工作,对于每个新任务,它循环使用避免线程们得到休息。这意味着你不能在 BackgroundWorker线程上调用 Abort了。

下面是使用BackgroundWorker最少的步骤:

  • 实例化 BackgroundWorker,为DoWork事件增加委托。
  • 调用RunWorkerAsync方法,使用一个随便的object参数。

这就设置好了它,任何被传入RunWorkerAsync的参数将通过事件参数的Argument属性,传到DoWork事件委托的方法中,下面是例子:

class Program {
  static BackgroundWorker bw = new BackgroundWorker();
  static void Main() {
    bw.DoWork += bw_DoWork;
    bw.RunWorkerAsync ("Message to worker");     
    Console.ReadLine();
  } 
  static void bw_DoWork (object sender, DoWorkEventArgs e) 
{
    // 这被工作线程调用
    Console.WriteLine (e.Argument);        // 写"Message to worker"
    // 执行耗时的任务...
  }

BackgroundWorker也提供了RunWorkerCompleted事件,它在DoWork事件完成后触发,处理RunWorkerCompleted事件并不是强制的,但是为了查询到DoWork中的异常,你通常会这么做的。RunWorkerCompleted中的代码可以更新Windows Forms 控件,而不用显示的信号编组,而DoWork中就可以这么做。

添加进程报告支持:

  • 设置WorkerReportsProgress属性为true
  • 在DoWork中使用“完成百分比”周期地调用ReportProgress方法,以及可选用户状态对象
  • 处理ProgressChanged事件,查询它的事件参数的 ProgressPercentage属性

ProgressChanged中的代码就像RunWorkerCompleted一样可以自由地与UI控件进行交互,这在更性进度栏尤为有用。

添加退出报告支持:

  • 设置WorkerSupportsCancellation属性为true
  • 在DoWork中周期地检查CancellationPending属性:如果为true,就设置事件参数的Cancel属性为true,然后返回。(工作线程可能会设置Cancel为true,并且不通过CancellationPending进行提示——如果判定工作太过困难并且它不能继续运行)
  • 调用CancelAsync来请求退出

下面的例子实现了上面描述的特性:

Code
posted @ 2008-12-17 15:25  cindymeng  阅读(434)  评论(0编辑  收藏  举报