I've been trying to get a handle on the Rx library and working it out in WPF with MVVM. I broken my application into components such as repository and the ViewModel. My repository in able to provide a Collection of Students one by one but the moment i try to add into the View bound ObservableCollection it throws a thread error. I 'd apreciate some pointer on to get this working for me.
Asked
Active
Viewed 7,836 times
7
-
possible duplicate of [Updating an ObservableCollection in a separate thread](http://stackoverflow.com/questions/2104614/updating-an-observablecollection-in-a-separate-thread) – Thomas Levesque Feb 20 '12 at 17:32
-
Try the following link which provides a thread-safe solution that works from any thread and can be bound to via multiple UI threads : http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony Apr 15 '14 at 19:22
3 Answers
8
You need to set the synchronization context correctly using
ObserveOn(SynchronizationContext.Current)
See this blog post
for an example.
Here's 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; }
}

Phil
- 42,255
- 9
- 100
- 100
-
this method work if the code is in the Xamls code behind but i need the ViewModel to add an entity. My source is an Async service called from a ViewModel. At that time the SynchronitaionContext.Current wont have any value in the ViewModel – Arshad Badar Khan Feb 21 '12 at 08:47
-
I've added an example that works for me. Note that I've added Rx-Main and Rx-WPF via NuGet. – Phil Feb 21 '12 at 08:48
-
My code is more or less the same but my collection fetch and assignment happens in the Constructor. Also I'm using Unity to resolve the class. I've added a detailed code here http://stackoverflow.com/questions/9377290/synchronizationcontext-current-is-null-on-resolving-with-unity-in-wpf – Arshad Badar Khan Feb 21 '12 at 12:05
1
Is your code running on a background thread? As it affects the UI, a View bound ObservableCollection can only be updated on the UI/Dispatcher thread.
See WPF ObservableCollection Thread Safety for a similar issue.

Community
- 1
- 1

Stephen Holt
- 2,360
- 4
- 26
- 34
1
Any change to the UI should be done by the Dispatcher
thread. A good practice if you have anthoer thread constantly changing the view model is to force property setters to use the dispatcher thread. In this case you make sure that you wont change a UI element on another thread.
Try:
public string Property
{
set
{
Dispatcher.BeginInvoke(()=> _property = value ) ;
OnPropertyChanged("Property");
}
get
{
return _property;
}
}

Sofian Hnaide
- 2,284
- 16
- 13