2013-02-08 28 views
0

因此,我正在處理我的第一個多線程WPF應用程序。請記住,我對於如何實現多線程有一點也不瞭解 - 我已經在幾個應用程序中完成了它,並且始終處理現有的代碼。這是我在WPF的第一次嘗試,它顯然與Windows窗體有很大不同...InvalidOperationException當WPF中的多線程

所以基本上我正在研究this example這奇怪的是沒有提到你必須實例化一個新線程並啓動它 - 我想作者覺得即使是像我這樣的新手也是如此。

在任何情況下,它都可以正常工作,直到我想更新我的UI控件的屬性時,我碰到一個InvalidOperationException,它說調用線程無法訪問控件因爲控制屬於不同的線程

所以基本上這是不工作線程安全的方式,但我在茫然,我應該怎麼解決這個問題?

這裏是我的代碼:

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; 
} 

如果任何人都可以在這裏提出解決方案或者解釋更多關於我正在使用的概念(我仍然很模糊),這樣我就可以足夠了解自己找到一個解決方案,這將非常感激。

在此先感謝!

編輯
錯誤還配備了,如果我得到的UI控件屬性TextReader tr = new StreamReader(txtSource.Text);也拋出該異常。

回答

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

條件是紅色下劃線錯誤'操作員'!'在任何情況下都不能應用於'方法組'的操作數' – Ortund 2013-02-08 13:10:26

+0

,因爲InvalidOperationException,執行會在執行HideProcessing()之前暫停 – Ortund 2013-02-08 13:11:47

0

你真的需要在這裏理解的是,你不能從UI線程訪問另一個線程的任何控制。

當你做

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

你想設置一個文本框(txtPreview)的值,在後臺線程左右。

你需要做的,就是閱讀在後臺線程文件內容,然後使用UI線程通過使用Dispatcher來更新文本框的值,:

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

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