2010-08-16 69 views
5

在我的Windows中,我有一個文本框,我喜歡從另一個線程更新(文本屬性)。這樣做時,我得到InvalidOperationException(請參閱標題)。我在谷歌解釋這個發現不同的鏈接,但我似乎仍然無法使其工作。WPF System.InvalidOperationException:調用線程無法訪問此對象,因爲不同的線程擁有它

我已經試過是這樣的:

窗口1代碼:

private static Window1 _myWindow; 
private MessageQueueTemplate _messageQueueTemplate; 
private const string LocalTemplateName = "LocalExamSessionAccessCodeMessageQueueTemplate"; 
private const string RemoteTemplateName = "RemoteExamSessionAccessCodeMessageQueueTemplate"; 

... 
public Window1() 
{ 
    InitializeComponent(); 
    _myWindow = this; 
} 

public static Window1 MyWindow 
{ 
    get 
    { 
     return _myWindow; 
    } 
} 

public void LogText(string text) 
{ 
    informationTextBox.Text += text + Environment.NewLine; 
} 
... 

在另一大類(實際上是一個spring.NET偵聽器適配器,聽某一個隊列,在另一個線程開始)。

var thread = new Thread(
    new ThreadStart(
     delegate() 
      { 
       Window1.MyWindow.Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.Normal, 
        new Action(
         delegate() 
          { 
           Window1.MyWindow.LogText(text); 
          } 
         )); 
      } 
     )); 

它不會引發錯誤,但Window1中LogText方法中的文本沒有被觸發,所以文本沒有更新。

所以基本上,我想更新另一個線程中運行的另一個類的TextBox組件。

回答

6
Window1.MyWindow.informationTextBox.Dispatcher.Invoke(
    DispatcherPriority.Normal, 
    new Action(() => Window1.MyWindow.informationTextBox.Text += value)); 
3

好,用Dispatcher.InvokeBeginInvoke肯定是要走的路,但你還沒有真正顯示不是創建一個線程之外的很多代碼 - 例如,你有沒有在你的第二個代碼塊開始線程。

如果你把Dispatcher.Invoke代碼放在之前得到InvalidOperationException的地方,應該沒問題。

+0

我很佩服你的耐心!我相信這是被問及的gazillionth時間! – Manfred 2010-08-16 09:36:37

+0

好吧,約翰,我知道這是,我已經搜索了其他問題,但還沒有找到我正在尋找的答案。我可以去閱讀關於調度程序和線程的大量鏈接,但事實是我沒有時間。我試圖去做其他人的建議,但它不起作用。 @Jon Skeet:開始我的第二個代碼塊的代碼在Spring.NET程序集中。他們創建線程來偵聽msmq隊列並觸發自定義適配器類中的方法。在這個類中,我想更新一個TextBox。 – 2010-08-16 10:04:43

+2

@Lieven:如果你想創建一個簡短但完整的程序來證明問題,那真的很有幫助。你可能會發現,通過這樣做,你可以自己發現問題。完整的程序不需要處理Spring等 - 只需創建一個定期更新UI的線程,或類似的東西。使用'Dispatcher' *就是這裏的答案 - 但是我們不能說明你在顯示的代碼中做了什麼錯誤。 – 2010-08-16 10:19:34

0

對於WPF,我發現這個結構:

BackgroundWorker bw = new BackgroundWorker(); 
    bw.DoWork += (s, e) => 
    { 
    }; 
    bw.RunWorkerCompleted += (s, e) => 
    { 
    }; 
    bw.RunWorkerAsync(); 

是最有用的。 RunWorkerCompleted塊通常會更新ObservableCollection或激發RaisePropertyChangedEvent。

相關問題