2010-08-16 1024 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。

相关问题