Updating ObservableCollection from another thread

I am trying to get an Rx library descriptor and work with it in WPF using MVVM. I split my application into components like repository and ViewModel. My repository is able to provide a collection of students one by one, but the moment I try to add an ObservableCollection to the overview binding, it throws a stream error. I would appreciate some pointer to make this work for me.

+6
source share
3 answers

You must correctly configure the synchronization context using

ObserveOn(SynchronizationContext.Current) 

See this blog post

http://10rem.net/blog/2011/02/17/asynchronous-web-and-network-calls-on-the-client-in-wpf-and-silverlight-and-net-in-general

for example.

Here is an example that works for me:

 <Page.Resources> <ViewModel:ReactiveListViewModel x:Key="model"/> </Page.Resources> <Grid DataContext="{StaticResource model}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <Button Content="Start" Command="{Binding StartCommand}"/> <ListBox ItemsSource="{Binding Items}" Grid.Row="1"/> </Grid> public class ReactiveListViewModel : ViewModelBase { public ReactiveListViewModel() { Items = new ObservableCollection<long>(); StartCommand = new RelayCommand(Start); } public ICommand StartCommand { get; private set; } private void Start() { var observable = Observable.Interval(TimeSpan.FromSeconds(1)); //Exception: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread. //observable.Subscribe(num => Items.Add(num)); // Works fine observable.ObserveOn(SynchronizationContext.Current).Subscribe(num => Items.Add(num)); // Works fine //observable.ObserveOnDispatcher().Subscribe(num => Items.Add(num)); } public ObservableCollection<long> Items { get; private set; } } 
+8
source

Does your code run on a background thread? Since this affects the user interface, the View ObservableCollection binding can only be updated in the user interface / dispatcher thread.

See WPF ObservableCollection Thread Safety for a similar issue.

+1
source

Any change to the user interface must be done by the Dispatcher thread. Good practice, if you have an anthoer thread constantly changing the view model, is to force property definition tools to use the dispatcher thread. In this case, you will make sure that you do not change the user interface element in another thread.

Try:

 public string Property { set { Dispatcher.BeginInvoke(()=> _property = value ) ; OnPropertyChanged("Property"); } get { return _property; } } 
+1
source

Source: https://habr.com/ru/post/908909/


All Articles