2010-10-21 117 views
1

我想創建一個包含表單進度條(只是一個GIF圖像)的線程。 我在大的方法之前調用了StartProgress()。基本上,當線程啓動時,它會加載ProgressBar表單(我想一直顯示,並在不需要時將其隱藏),並且ProgressActive設置爲true,它應顯示錶單,直到ProgressActive爲false,然後窗體應該隱藏(直到進度再次激活)。以下是我迄今爲止,但它在我:(凍結了需要線程幫助-C#Windows窗體

public static string ProgressInfo="Test"; 
    public static bool ProgressActive=true; 
    public static bool ThreadStarted = false; 

    public static void StartProgress() 
    { 
     while (!ThreadStarted) 
     { 
      Thread t = new Thread(new ThreadStart(Progress)); 
      ThreadStarted = true; 
      t.Start(); 
     } 

    } 
    public static void Progress() 
    { 
     while (ThreadStarted) 
     { 

      LoadingBar lb = new LoadingBar(); 
      lb.Show(); 
      lb.TopMost = true; 
      while (ThreadStarted) 
      { 
       if (ProgressActive) 
       { 
        lb.Visible = true; 
        lb.lblLoadingStatus.Text = ProgressInfo; 
       } 
       else 
       { 
        lb.Visible = false; 
       } 
       Thread.Sleep(1000); 
      } 
     } 

    } 

編輯:我想要一個靜態類內做到這一點

回答

1

凍結是由於您試圖更改您的工作線程中包含在UI線程中的進度欄​​。我建議將你的工作進程函數中的事件引發到UI線程上的處理程序。你將需要在線程上調用處理程序,如下所示。

private object _lock = new object(); //should have class scope 

private void ShowProgressControl(EventArgs e) 
{ 
    if (this.InvokeRequired) 
    { 
    lock (_lock) 
    { 
     EventHandler d = new EventHandler(ShowProgressControl); 
     this.Invoke(d, new object[] { e }); 
     return; 
    } 
    } 
    else 
    { 
    //Show your progress bar. 
    } 
} 

享受!

+0

謝謝,但我使用靜態類,所以「這個」不起作用:( – Spooks 2010-10-21 15:06:49

+0

@ Spooks - 你可能需要考慮讓這個靜態類只用於你的工作進程,讓它暴露並且事件發生,然後在(UI線程)主持你的應用的主表單中使用這個事件。 – Doug 2010-10-21 15:29:37

+0

聽起來像是一個好主意。線程t =新的線程(新的線程啓動(進度)); 這是否創建一個新的工作進程(不消耗UI線程)? – Spooks 2010-10-21 15:43:10

4

沒有任何理由不使用的BackgroundWorker如果使用.NET 2.0或更高版本?

的原因,我說,是因爲BackgroundWorker的是基於事件的,所以它暴露了像ProgressChanged事件可以減少代碼的整體規模。

+0

原因是我錯過了它。編輯:注意我想在一個完整的靜態類 – Spooks 2010-10-21 14:40:03

0

您應該創建p主線程上的進度條。

確保您的繁重程序從另一個線程運行。

1

問題是,您需要一個消息循環才能使任何UI元素正常工作。由於您在工作線程中創建表單,因此沒有消息循環運行。要創建消息循環,您必須撥打Application.RunForm.ShowDialog,這兩者都是阻止呼叫。顯然,解決方案會掛斷你的工作線程。

最好的辦法是創建一個專門用於運行消息循環的獨立線程,並可以安全地處理表單和控件。讓工作線程定期將進程信息發佈到可以在工作線程和UI線程之間共享的變量。然後讓UI線程定期輪詢(使用System.Windows.Form.Timer)該共享變量並相應地更新UI。

作爲便箋,我會避免使用Control.InvokeControl.BeginInvoke將進度信息推送到UI線程。您的情況似乎保證了投票方式。超過推寧願投票的原因是:

  • 它打破了用戶界面和工作線程Control.Invoke強加之間的緊耦合。
  • 它將UI線程更新的責任置於UI線程上,無論如何它應該屬於它。
  • UI線程可以決定更新應該發生的時間和頻率。
  • 不存在UI消息泵被超載的風險,這與工作線程啓動的封送處理技術的情況相同。
  • 工作線程在進行下一步之前(即在UI線程和工作線程上獲得更多的吞吐量),不必等待已執行更新的確認。