2011-12-18 87 views
0

我有一個應用程序,每次點擊此按鈕時都需要按鈕添加特殊文本添加到文本框,但是當單擊此按鈕時,所有時間都等待並一起輸入所有文本。使用Thread.Sleep時UI未更新

什麼是問題?

例如:

private void button2_Click(object sender, RoutedEventArgs e) 
     { 
      Random rand = new Random(DateTime.Now.Millisecond); 
      textBox1.Text = ""; 
      for (int i = 0; i < 10; i++) 
      { 
       textBox1.Text += rand.Next(1,10) + "\n"; 
       System.Threading.Thread.Sleep(1000); 
      } 
     } 

感謝。

回答

6

你在UI線程上睡覺。
這會凍結UI。

而是使用BackgroundWorker及其進度事件。

1

文本實際被添加到您的文本框,在1秒的間隔,你就看不到它,直到循環結束了,因爲你已經把GUI的線程睡眠,它是無法自行更新。

1

@Slaks是正確的;你在睡覺UI線程。

我會建議一個計時器作爲更優雅的解決方案。請注意,在另一個線程中引發的事件(例如來自後臺工作人員或計時器)將需要編組回到表單的UI線程。

0

讓線程睡眠會讓你的主線程睡眠。

下可能工作

使功能

private void wait(int ms) 
{ 
    for(int x=0;x<ms;x++) 
    { 
     Thread.Sleep(1); 
     System.Windows.Forms.Application.DoEvents(); 
    } 
} 

這將每個MiliSecond

後做活動,你可以用它

private void button2_Click(object sender, RoutedEventArgs e) 
     { 
      Random rand = new Random(DateTime.Now.Millisecond); 
      textBox1.Text = ""; 
      for (int i = 0; i < 10; i++) 
      { 
       textBox1.Text += rand.Next(1,10) + "\n"; 
       wait(1000); 
      } 
     } 
+0

這將暫停期間發生的任何其他操作睡覺;也因爲循環,你將被調用sleep()和調用DoEvents()1000倍成一排,它不能很好的性能。 – 2011-12-18 17:43:51

+0

好吧,這是一種可以讓你的用戶界面freez無法延遲的方式。 – 2011-12-18 17:46:25

+0

不是一個好的答案。因爲1)的DoEvents()是一個危險的特技和2)的Sleep()具有約20毫秒的分辨率。你的方法會睡15-25倍的時間比你想象的。 – 2011-12-18 17:49:16

0

最好的方式實現這一目標是將BackgroundWorker與INotifyPropertyChanged結合使用

public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

和執行財產

private string _value; 
    public string Value 
    { 
     get { return _value; } 
     set 
     { 
      if(value.Equals(_value)) return; 
      _value = value; 
      NotifyPropertyChanged("Value"); 
     } 
    } 

調用方法

private void Foo() 
    { 
     var rand = new Random(DateTime.Now.Millisecond); 

     for (var i = 0; i < 50; i++) 
     { 
      Value += rand.Next(1, 10) + "\n"; 
      System.Threading.Thread.Sleep(500); 
     } 
    } 

事件DoWork的BackgroundWorker的這樣

private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     var worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     worker.RunWorkerAsync(); 
    } 


    void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     Foo(); 
    }