2014-01-09 29 views
1

我想在單擊按鈕啓動後更改wpf控件狀態。在啓動線程之前無法更改WPF控件狀態

這張照片是我想要的。

what I want

以下是我的代碼

private bool _bWorking = false; 
public delegate void UpdateStatusDelegate(); 

private void SetStatus(bool bEnable) 
{ 
    if (bEnable) 
    { 
     tbName.IsReadOnly = false; 
     barStatus.Visibility = Visibility.Hidden; 
     btnStart.IsEnabled = true; 
     btnStop.IsEnabled = false; 
     btnClose.IsEnabled = true; 
    } 
    else 
    { 
     tbName.IsReadOnly = true; 
     barStatus.Visibility = Visibility.Visible; 
     btnStart.IsEnabled = false; 
     btnStop.IsEnabled = true; 
     btnClose.IsEnabled = false; 
    } 
} 

internal void UpdateStatus() 
{ 
    SetStatus(true); 
    _bWorking = false; 
} 

private void ThreadFunc() 
{ 
    //for (; ;) 
    //{ 
    // // do something here 
    // if (_bWorking == false) 
    //  break; 
    //} 
    Thread.Sleep(500); 
    this.Dispatcher.Invoke(new UpdateStatusDelegate(UpdateStatus)); 
} 

private void btnStart_Click(object sender, RoutedEventArgs e) 
{ 
    _bWorking = true; 
    SetStatus(false); 
    this.UpdateLayout();//this.InvalidateVisual(); 
    try 
    { 
     Thread t = new Thread(new ThreadStart(() => 
     { 
      ThreadFunc(); 
     })); 
     t.IsBackground = true; 
     t.Name = "test status"; 
     t.Start(); 

     while (t.IsAlive) 
     { 
      // wait thread exit 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    }   
} 

private void btnStop_Click(object sender, RoutedEventArgs e) 
{ 
    _bWorking = false; 
    SetStatus(true); 
} 

但實際上我點擊按鈕啓動後,該UI似乎凍結,線程退出,成爲正常的UI。

我的VS是VS2010。

Force a WPF control to refresh?

這個職位不適合我。

編輯總結:

附加委託無效UpdateStatusDelegate()和功能UpdateStatus()我的代碼

+0

可能重複[如何更新在C#中的另一個線程的GUI?](http://stackoverflow.com/questions/661561/how-to -update-the-gui-from-another-thread-in-c) – Gusdor

+0

謝謝,但它對我不起作用。那篇文章談到了WinForm,我的問題是關於WPF。 – Rock

回答

3

//等待線程退出

後臺線程的整點到不是通過阻止你的UI線程等待它。別。

取而代之,讓線程在完成時通知您的用戶界面。

+0

我的線程不改變UI – Rock

+0

但是你想在線程完成後改變你的UI。如果您*等待線程,則不需要線程,您可以在沒有第二個線程的情況下執行此操作。你不想*等待,你希望你的線程通知你的用戶界面,當它可以做你想做的事情時,線程完成。 – nvoigt

+0

我添加委託無效UpdateStatusDelegate()和函數UpdateStatus()。它仍然沒有工作。 – Rock

0

嘗試使用BackgroundWorker組件它可能會幫助你。欲瞭解更多信息,請檢查MSDN article

0

可行的代碼

public delegate void UpdateStatusDelegate(); 
    private bool _bWorking = false; 

    private void SetStatus(bool bEnable) 
    { 
     if (bEnable) 
     { 
      tbName.IsReadOnly = false; 
      barStatus.Visibility = Visibility.Hidden; 
      btnStart.IsEnabled = true; 
      btnStop.IsEnabled = false; 
      btnClose.IsEnabled = true; 
     } 
     else 
     { 
      tbName.IsReadOnly = true; 
      barStatus.Visibility = Visibility.Visible; 
      btnStart.IsEnabled = false; 
      btnStop.IsEnabled = true; 
      btnClose.IsEnabled = false; 
     } 
    } 

    internal void UpdateStatus() 
    { 
     SetStatus(true); 
    } 

    private void ThreadFunc() 
    { 
     try 
     { 
      // use Stopwatch to simulate jobs 
      var watch = Stopwatch.StartNew(); 
      for (; ;) 
      { 
       var elapsedMs = watch.ElapsedMilliseconds; 
       if (elapsedMs > 10000 // 10 seconds 
        || _bWorking == false) 
       { 
        break; 
       } 
      } 
      watch.Stop(); 
      this.Dispatcher.Invoke(new UpdateStatusDelegate(UpdateStatus)); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
     _bWorking = false; 
    } 

    private void btnStart_Click(object sender, RoutedEventArgs e) 
    { 
     try 
     { 
      _bWorking = true; 
      SetStatus(false); 
      Thread t = new Thread(new ThreadStart(() => 
      { 
       ThreadFunc(); 
      })); 
      t.IsBackground = true; 
      t.Name = "test status"; 
      t.Start(); 
      //while (t.IsAlive) 
      { 
       // wait thread exit 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 

    private void btnStop_Click(object sender, RoutedEventArgs e) 
    { 
     _bWorking = false; 
     SetStatus(true); 
    }