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:
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";
});
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With