2010-12-23 49 views
1

我需要在打开文件时显示进度对话框,这是一个耗时的操作。要做到这一点,我用我的打开文件功能里面以下:Form.Show()间歇性地显示线程中的表单

  //some code 
      ... 
      ... 
      ... 
      bool done = false; 

      //Show progress in a separate thread. 
      System.Threading.ThreadPool.QueueUserWorkItem((x) => 
      { 
       using (var progressDialog = new ProgressDialog()) 
       { 
        progressDialog.TopMost = true; 
        progressDialog.Show(); 

        while (!done) 
        { 
         if(progressDialog.Message != this.strProgressMsg) 
          progressDialog.Message = this.strProgressMsg; 

         Application.DoEvents(); 
        } 

        progressDialog.Close(); 
       } 
      }); 

      .... 
      .... 
      done = true; 
      .... 
      .... 

问题: 进度对话框显示了一些时间,有时没有。我的文件打开功能在主线程中运行。有人能指出我为什么会发生这种情况吗?

回答

5

你有这个倒退。下面是它如何工作:

  1. 分拆一个线程来打开文件,并调用它回使用progressDialog.Invoke()执行GUI更新主线程。 (它不应该设置strProgressMsg并等待其他内容注意更改 - 是否将更新直接发送到对话框。)
  2. 从主线程以模态方式显示进度对话框。

因此,像这样:

using (var progressDialog = new ProgressDialog()) { 
    progressDialog.TopMost = true; 

    System.Threading.ThreadPool.QueueUserWorkItem((x) => 
    { 
     try { 
      // this represents whatever loop you use to load the file 
      while (...) { 
       // do some work loading the file 

       // update the status 
       progressDialog.Invoke(new MethodInvoker(
        () => progressDialog.Message = "Hello, World!")); 
      } 
     } finally { 
      // done working 
      progressDialog.Invoke(new MethodInvoker(progressDialog.Close)); 
     } 
    }); 

    // this will block until the thread closes the dialog 
    progressDialog.ShowDialog(); 
} 
1

形式需要一个消息来正常工作。你可以用Application.RunForm.ShowDialog开始一个消息循环,两者都阻塞调用,所以显然这种策略在工作线程中不会很好地工作。这里有两种方法可以让它正常工作。

  • 在UI线程创建progressDialog,并通过Control.Invoke将消息发送给它的新进展信息进行更新。
  • 在UI线程上创建progressDialog并使用System.Windows.Forms.Timer轮询变量以获取工作线程发布的新进度信息。

在这种情况下,轮询方法是优选在Control.Invoke方法的,因为:

  • 它打破用户界面和工作线程Control.Invoke强加之间的紧耦合。
  • 它将UI线程更新的责任置于UI线程上,无论如何它应该属于它。
  • UI线程可以决定更新应该发生的时间和频率。
  • 不存在UI消息泵被超载的风险,这与工作线程启动的封送处理技术的情况相同。
  • 工作线程在进行下一步之前(即在UI线程和工作线程上获得更多的吞吐量),不必等待已执行更新的确认。