-4

How should I edit WPF data that exists outside a C# task? I have defined a UI using the standard WPF template. The grid contains only:

<TextBlock x:Name="myTextBox" Text="Original Text" />

In my code I have:

using System.Threading.Tasks;
using System.Windows;

namespace UpdateGUI
{
  public partial class MainWindow : Window
  {
    private int myInt;

    public MainWindow()
    {
      InitializeComponent();

      myInt = 0;
      Task.Factory.StartNew(() =>
      {
        myInt++;
        myTextBox.Text = "New Text";
      });
    }
  }
}

This throws the following exception:

The calling thread cannot access this object because a different thread owns it.

Which thread owns myTextBox? Why don't I see this error when I edit myInt?

4444
  • 3,541
  • 10
  • 32
  • 43
chart328
  • 113
  • 1
  • 6
  • Only the UI thread should update UI elements. If another thread needs to update the UI, it should ask the UI thread to do it. One way to do this is via the [Dispatcher class](https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke(v=vs.110).aspx). – Yacoub Massad Sep 07 '16 at 20:41
  • 1
    Or you could use two-way binding mechanism. Bind the textbox to a property on a model, then you can update the model, which will update the textbox automatically. – rmcsharry Sep 07 '16 at 20:42
  • The problem with your sample code is that it's so simplistic, that there is nothing justifying the need to start another thread. If you have a more specific need that explain why you spawn a thread, maybe we can guide you more specifically. – sstan Sep 07 '16 at 20:51
  • You need to either use async await or invoke the UI update back to the UI thread using Dispatcher invoke. This was marked as a dupe, which is true. But linked to a WinForm solution, which does not carry over to WPF. The dupe answer should link to a WPF solution. – Tom Sep 07 '16 at 20:52
  • 1
    @rmcsharry Data binding in WPF is the best thing since sliced bread. It's well worth the time to learn to use it. – Fuzhou Hu Sep 07 '16 at 20:55

1 Answers1

0

What you are trying to do is impossible. Your code runs on in its own thread separate from the UI thread.

You need to learn more about WPF. To get this working there are 2 solutions I know of:

  1. Use a two-way binding to a model property
  2. Implement a dispatcher

Option 1 is the usual way to do this, so learn about two way bindings. A dispatcher is overkill for what you are trying to do.

4444
  • 3,541
  • 10
  • 32
  • 43
rmcsharry
  • 5,363
  • 6
  • 65
  • 108