Updating an ObservableCollection in a separate thread

thread-safe observablecollection
observablecollection thread affinity
enablecollectionsynchronization observablecollection
how to update observablecollection in wpf
concurrent observablecollection
multi-threaded observablecollection
must create dependencysource on same thread as the dependencyobject mvvm
binding to an asynchronous collection

In a WPF application an ObservableCollection is filled and updated by LINQ to SQL queries. Then UI objects are updated using values from this ObservableCollection.

Is it possible and reasonable that operations of updating this ObservableCollection by LINQ to SQL queries were executed in a separate thread?

If yes, will, in this case, it be one and the same instance of this ObservableCollection? (I mean, if it is not the same one for taking values from LINQ datacontext and the one for giving values to update UI, then I will not be able to update UI)

With the built-in ObservableCollection<T> class, you can't change the content from a separate thread if the UI is bound to the collection, it throws a NotSupportedException (but change notification for properties of collection items works fine). I wrote an AsyncObservableCollection<T> class to handle this case. It works by invoking the event handlers on the UI synchronization context

Thread Safe Improvement for ObservableCollection, This was because I expected to be using the Model side with many different interesting at “Have worker thread update ObservableCollection that is bound to a  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:

.Net 4.5 provides a solution within the BindingOperations class.

You can now use the BindingOperations.EnableCollectionSynchronization method as follows:

private readonly object _personCollectionLock;
private ObservableCollection<Person> _personCollection;

public ObservableCollection<Person> PersonCollection
{
  get { return _personCollection; }
  set
  { 
    _personCollection = value;
    BindingOperations.EnableCollectionSynchronization(_personCollection, _personCollectionLock);
  }

I have only just tried this in my development environment but everything seems to be working correctly now when I update the collection from a background thread.

There is a more in-depth discussion of this solution at: http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification

The MSDN entry for this method is at: https://msdn.microsoft.com/en-us/library/system.windows.data.bindingoperations.enablecollectionsynchronization(v=vs.110).aspx

WPF Tip #10 - Update ObservableCollection From a , post about updating ObservableCollection from background threads. to an ObservableCollection had to dispatch calls to the UI thread. Pete Brown has a detailed blog post about updating ObservableCollection from background threads. I wanted to share the link to his post from 2012 and share a quick code snippet that illustrates how to do this in .NET 4.5 and later. Before .NET 4.5, background updates to an ObservableCollection had to dispatch calls to the UI thread.

In our app, we have a TreeView bound to an ObservableCollection, which we regularly update in a background thread, requesting data from our storage. It works perfectly!

Whoops. I was mis-informed =))

Right, we're actually subclassing the ObservableCollection<T> and override the OnCollectionChanged method to avoid the UI crossthreading exception. We're using this solution:

public class MTObservableCollection<T> : ObservableCollection<T>
{
   public override event NotifyCollectionChangedEventHandler CollectionChanged;
   protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   {
      var eh = CollectionChanged;
      if (eh != null)
      {
         Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                 let dpo = nh.Target as DispatcherObject
                 where dpo != null
                 select dpo.Dispatcher).FirstOrDefault();

        if (dispatcher != null && dispatcher.CheckAccess() == false)
        {
           dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
        }
        else
        {
           foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
              nh.Invoke(this, e);
        }
     }
  }
}

Without that override you'd get an exception like that

System.NotSupportedException : This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

Now the only problem we have is the selected item position, in some cases if the currently selected item is deleted from the collection the TreeView moves the selection to the next item (which causes some other unnecessary UI actions in our app). But that's a small issue.

Modifying ObservableCollection from worker threads in WPF , All works well until you are working with Threads and your worker threads try to its SourceCollection from a thread different from the Dispatcher thread. That is it, now you can update the ObservableCollection from worker  NotSupportedException: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread. SOLUTION. If you are using WPF 4.5 then all you have to do is this: Create the ObservableCollection in the main thread (usually done in the ViewModel)

Trying to understand your question here:

Scenario 1
1. LINQ to SQL retrieves data set from database and adds to ObservableCollection A.
2. Periodically, more data is retrieved from database and added to A. Old data is removed from A.

Scenario 2
1. LINQ to SQL retrieves data set from database and adds to ObservableCollection A.
2. Periodically, data in A is updated with new data from database (no add/remove).

With Scenario 1, you're going to have to use the UI thread. The UI thread owns the ObservableCollection and you'll get an exception if you try to use it in another thread.

With Scenario 2, thumbs up. As long as you don't try to add or remove items from the collection itself, you can update the item as much as you want in a background thread.

https://social.msdn.microsoft.com/Forums/en-US/9b7, The call must occur before using the collection on a different thread or before attaching For instance, ObservableCollection<T> guarantees this, provided that all to update the collection (add or remove items) on a "data-gathering" thread,  Modifying the collection on the background thread. When an ObservableCollection is modified, it raises an event. Events are handled synchronously. Event handlers respond on the same thread as the modification. The handler completes before the Add or Remove method returns. This means that you can’t modify an ObservableCollection in a background thread.

I did not receive the same System.NotSupportedException, but unfortunately my UI did not Update properly if I set the my ObservableCollectiony<MyType> from another thread.

The only thing that worked for me is presented by https://www.codeproject.com/Tips/1111432/Update-data-to-WPF-control-from-another-thread:

In ViewModel
private SynchronizationContext _syncContext = SynchronizationContext.Current;

private ObservableCollection<PackageModel> _packageModelList;
public ObservableCollection<PackageModel> PackageModelList
{
     get => _packageModelList;
     set
     {
         if (_packageModelList == value)
             return;
         packageModelList = value;
         RaisePropertyChanged("PackageModelList");
     }
}      
In other thread
 _syncContext.Send(x => { PackageModelList = OtherThreadPackageModels; },null);

Hope this helps others.

BindingOperations.EnableCollectionSynchronization Method , This topic describes how to manage multi-thread data updates. business logic does not depend on when separate data updates are executed, new Object(); public ObservableCollection<Customer> Customers { get; set; }  5 Answers5. Active Oldest Votes. 27. With the built-in ObservableCollection<T> class, you can't change the content from a separate thread if the UI is bound to the collection, it throws a NotSupportedException (but change notification for properties of collection items works fine).

Managing Multi-Thread Data Updates | WPF Controls, Here's the main features of the thread-safe observable collection: Both collections contain the same data and the UI should be updated  As you may have noticed, it is not possible to modify the contents of an ObservableCollection on a separate thread if a view is bound to this collection : the CollectionView raises a NotSupportedException : This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread To illustrate this, let’s take a simple example : a ListBox bound to a collection of strings in the ViewModel :

Thread-safe observable collection in .NET, I have a thread-safe observable collection. It works fine for wpf After this setup you can update the collection from a different thread. Here is a  WPF 4.5 addresses several important customer requests including the ability to have cross-thread change notification for collections - the topic of this post. Update 1/20/2012: I have posted a set of updates to this post with additional information about the details, as well as a few code changes. Be sure to read that post as well as this one.

Observable collection thread-safe for xamGrid, ItemSource , but when we then try to update the collection from different threads, we'll get this error because ObservableCollection isn't thread 

Comments
  • a posible alternative stackoverflow.com/questions/12881489/…
  • Or you can try this which is comletely thread-safe, works from any thread, and can be databound by multiple UI threads : codeproject.com/Articles/64936/…
  • Nice job on the collection!!
  • @Thomas Levesque how to deal with "ghosts" (probably because the UI is enemerating while content is being added). See stackoverflow.com/questions/13624289/…. Do you have a solution for that? Perhaps some locking required?
  • How is that possible? Surely you are marshaling back to the UI thread to apply the changes from your data storage? Otherwise, you'd get an exception...
  • You have to create a sub class of ObservableCollection<T> that marshalls the CollectionChanged event back to the UI thread. I find that this is easier to manage than having the ViewModel managing update.
  • Thanks, Kent, Nigel -- you are right! I've corrected my answer, it was my mistake.