2010-12-23 51 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線程和工作線程上獲得更多的吞吐量),不必等待已執行更新的確認。