3

I just noticed what I can update binding source from another thread and it just works.

So I prepared a demo below and my questions are:

  • Why binding works? Why rising notification from another thread doesn't throws?
  • Is it legal to update source from another thread like this?

I was always using and telling to others to use Dispatcher.Invoke, but maybe I simply don't know something? Maybe binding is always guaranteed to update its target in UI thread or something like this?


<TextBox x:Name="textBox" Text="{Binding Text}" />

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string Text { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;

        Task.Run(() =>
        {
            Thread.Sleep(3000); // just wait long enough to ensure window is shown

            // works
            Text = "123";
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));

            // will crash with
            // System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it'
            textBox.Text = "123";
        });
    }
}
Sinatr
  • 20,892
  • 15
  • 90
  • 319

1 Answers1

3

It's perfectly legal to set a source property on a background thread. The framework handles the marshaling for you under the hood.

If you however try to add or remove items from a source collection, it's a different story:

How to update only a property in an observable collection from thread other than dispatcher thread in WPF MVVM?

Target properties, or more exactly properties of DependencyObjects, can only be accessed on the thread on which the object was originally created though. But you don't need to use a dispatcher to set view model properties from a background thread.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • 1
    Updating (e.g. calling `Add()` method) of **bound** `ObservableCollection` will indeed throw (different) exception. Assigning a **new** instance or if it's unbound will just work. Interesting... Any kind of proof what assigning can be done in any (namely in non-ui) thread? – Sinatr Apr 09 '20 at 11:23
  • @Sinatr: You should be able to set data bound source properties but not modifying data bound collections. – mm8 Apr 09 '20 at 11:25