2013-02-08 3 views
0

그래서 첫 번째 다중 스레드 WPF 응용 프로그램을 만들고 있습니다. 멀티 스레딩을 구현하는 방법에 대해 거의 이해할 수 없다는 점을 명심하십시오. 몇 가지 응용 프로그램에서 해본 결과 항상 기존 코드를 처리했습니다. 이것은 WPF에서 Windows Forms과 완전히 다른 WPF에서의 첫 번째 시도입니다 ...WPF에서 멀티 스레딩 할 때 InvalidOperationException이 발생했습니다.

기본적으로 나는 이상하게도 새 스레드를 인스턴스화하고 시작해야한다는 것을 언급하지 않고 this example에서 작업하고 있습니다. - 필자는 나 자신과 같은 초보자에게조차도 자기 자신이 분명하다고 느꼈다고 생각한다.

어쨌든 이라고 말한 지점에서 내 UI 컨트롤의 속성을 업데이트 할 시점까지는 아무런 문제가 없습니다. 호출 스레드가 컨트롤에 액세스 할 수 없습니다. 컨트롤이 다른 스레드에 속해 있기 때문에 여기에

내 코드의 ...

그래서 기본적으로이 작업 스레드 안전한 방법이 아니다,하지만 난이 문제를 해결하는 방법에 관해서 손실에 있어요 :

string fn = ""; 

private void btnBrowse_Click(object sender, RoutedEventArgs e) 
{ 
    if (lblActivity.Visibility != System.Windows.Visibility.Hidden) 
    { 
     lblActivity.Visibility = System.Windows.Visibility.Hidden; 
    } 
    if (lstResult.Items.Count != 0) 
    { 
     lstResult.Items.Clear(); 
    } 

    OpenFileDialog ofd = new OpenFileDialog(); 

    Nullable<bool> result = ofd.ShowDialog(); 

    if (result == true) 
    { 
     txtSource.Text = ofd.FileName; 
     txtDest.Text = ofd.FileName; 
     fn = ofd.SafeFileName; 

     PopulateControlsDuingLongRefreshCall("read"); 
    } 
} 

private void PopulateControlsDuingLongRefreshCall(string action) 
{ 
    ShowProcessing(); 

    ThreadStart ts = delegate 
    { 
     switch (action) 
     { 
      case "format": 
       Populate(); 
       CleanData(); 
       break; 
      case "read": 
       TextReader tr = new StreamReader(txtSource.Text); 
       txtPreview.Text = tr.ReadToEnd(); 
       break; 
     } 

     Dispatcher.BeginInvoke(DispatcherPriority.Normal, (EventHandler)delegate 
     { 
      HideProcessing(); 
     }, null, null); 

    }; 
    Thread thr = new Thread(ts); 
    thr.Start(); 
} 

private void ShowProcessing() 
{ 
    recProcessing.Visibility = Visibility.Visible; 
} 
private void HideProcessing() 
{ 
    recProcessing.Visibility = Visibility.Collapsed; 
} 

누구나 솔루션을 제안 할 수 있거나 내가 사용하고있는 개념에 대해 더 설명 할 수 있다면 (필자는 아직도 그다지 익숙하지 않다.) 스스로 해결책을 찾을 수있을만큼 충분히 이해할 수 있다면 많은 도움이 될 것이다.

미리 감사드립니다. 나는 TextReader tr = new StreamReader(txtSource.Text); 또한 예외를 던지는 UI 컨트롤 속성을 얻고 경우

편집
오류도납니다.

답변

1
대리자에서

보다는 액세스 txtSource 직접하는 위해 StreamReader를 반환하는 다음 함수를 사용해보십시오 :

private StreamReader GetTxtSource() 
    { 
     if (!this.Dispatcher.CheckAccess()) 
     { 
      return this.Dispatcher.Invoke(new Func<StreamReader>(this.GetTxtSource)) as StreamReader;     
     } 
     return new StreamReader(txtSource.Text); 
    } 

대신() txtSource.Dispatcher.CheckAccess를 사용해야 할 수도 있습니다.

+0

조건은 빨간색 오류로 밑줄 '연산자 '!' 어떤 경우에도 'method group'유형의 피연산자에 적용 할 수 없습니다. – Ortund

+0

InvalidOperationException으로 인해 HideProcessing()이 실행되기 전에 실행이 중지됩니다. – Ortund

0

여기서 정말로 알아야 할 것은 UI 스레드가 아닌 다른 스레드의 컨트롤에 액세스 할 수 없다는 것입니다.

그래서 당신은 백그라운드 스레드에서, 당신은 텍스트 상자 (txtPreview)의 값을 설정하려는

case "read": 
      TextReader tr = new StreamReader(txtSource.Text); 
      txtPreview.Text = tr.ReadToEnd(); 
      break; 

을 수행 할 때.

당신이해야 할 일은, 디스패처를 사용하여 텍스트 상자의 값을 업데이트하는 백그라운드 스레드에서 파일 내용을 읽은 다음 UI 스레드를 사용하는 것입니다

case "read": 
      TextReader tr = new StreamReader(txtSource.Text); 
      string content = tr.ReadToEnd(); 

      Dispatcher.Invoke((Action)(() => 
      { 
       txtPreview.Text = content; 
      })); 
      txtPreview.Text = tr.ReadToEnd(); 
      break;