views:

91

answers:

3

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.

+2  A: 

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.

Jon Skeet
I admire your patience! I believe this is the gazillionth time that has been asked!
John
Well, John, I know it is, and I have searched those other questions but haven't found the answer I was looking for. I could go and read numerous links on Dispatchers and threads, but the truth is that I haven't got the time for it. I tried to do what others suggested, but it doesn't work.@Jon Skeet: The code starting the thread of my second block of code is in the Spring.NET assemblies. They create threads that listen to a msmq queue and trigger a method in a custom adapter class. In this class I want to update a TextBox.
Lieven Cardoen
@Lieven: It would really, really help if you'd create a short but complete program that demonstrates the problem. You may well find that by doing that, you find the problem yourself. The complete program doesn't need to deal with Spring etc - just create a thread which regularly updates the UI, or something like that. Using `Dispatcher` *is* the answer here - but we can't tell what you're doing wrong within the code you've shown.
Jon Skeet
Well, that's it, I don't want a thread that regularly updates the UI, I want another thread directly accessing a UI component. I cannot control the way this thread is started. I think my question cannot be clearer. There's the UI component Textbox and another thread that wants to set the text value of this TextBox.
Lieven Cardoen
A: 

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.

amaca
+1  A: 
Window1.MyWindow.informationTextBox.Dispatcher.Invoke(
    DispatcherPriority.Normal,
    new Action(() => Window1.MyWindow.informationTextBox.Text += value));
Lieven Cardoen