2014-01-09 2 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 스레드를 차단하여 대기하십시오. 하지마.

대신 스레드가 완료되면 UI에 알리십시오.

+0

내 스레드 UI를 변경하지 않습니다 – Rock

+0

하지만 스레드가 완료된 후 UI를 변경하려고합니다. 스레드에 대해 * 대기 *하면 스레드가 필요하지 않으며 두 번째 스레드없이이 작업을 수행 할 수 있습니다. 스레드가 완료 될 때 수행하려는 작업을 수행 할 수있을 때 스레드가 UI에 알리고 싶습니다. – nvoigt

+0

대리자 void 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); 
    } 
관련 문제