Lieven Cardoen
Lieven Cardoen

Reputation: 25979

WPF System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it

In my Windows I have a TextBox which I like to update (text property) from another thread. When doing so, I get the InvalidOperationException (see title). I have found different links in google explaining this, but I still can't seem to make it work.

What I've tried is this:

Window1 code:

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

In another class (actually a spring.NET Listener adapter, listening to a certain queue, started in another thread).

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

It doesn't throw an error, but the text in the LogText method in Window1 isn't triggered, so the text isn't updated.

So basically, I want to update this TextBox component from another class running in another thread.

Upvotes: 7

Views: 7147

Answers (3)

Lieven Cardoen
Lieven Cardoen

Reputation: 25979

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

Upvotes: 9

amaca
amaca

Reputation: 1480

For WPF, I find this construct:

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

to be the most useful. The RunWorkerCompleted block will typically update an ObservableCollection or fire off a RaisePropertyChangedEvent.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503799

Well, using Dispatcher.Invoke or BeginInvoke is definitely the way to go, but you haven't really shown much code other than creating a thread - for example, you haven't started the thread in your second code block.

If you put the Dispatcher.Invoke code in the place where previously you were getting an InvalidOperationException, it should be fine.

Upvotes: 4

Related Questions