Asynchronously adding to ObservableCollection (or an alternative)

16,600

Solution 1

Since your ObservableCollection is bound to UI hence it gets generated on UI thread so any further updates (delete/add/clear) have to be on the same UI thread. It doesn't allow updates from another thread.

However, what you can do is to create an instance of your class (or all time consuming operation on background thread) and once you are done, add the object in ObservableCollection using Dispatcher of your UI thread like this -

App.Current.Dispatcher.BeginInvoke((Action)delegate()
                          {
                              observableCollection.Add(instanceOfYourClass);
                          });

What Dispatcher do is put the operation on its associated thread. Hence, the item will always be added on UI thread but can be created in background thread.

Here are few links which might get you going - Updating from BW and the other one is here

Solution 2

With .net 4.5 you can use EnableCollectionSynchronization

 object lockObj = new object();
        BindingOperations.EnableCollectionSynchronization(yourObservableCollection, lockObj);
Share:
16,600
oli.G
Author by

oli.G

Updated on June 19, 2022

Comments

  • oli.G
    oli.G almost 2 years

    Here's what I have - a ListBox with an ItemsSource set to a ObservableCollection<T> - where T is my custom class representing a file, containing just 2 DependencyProperties: Filename and ThumbnailPath. - The listbox also has a custom DataTemplate defined, in order to nicely display a image and filename under it.

    The purpose of the listbox is to display video files in the current folder (selected in a TreeView), with thumbnails (generated asynchronously; not part of this problem).

    So when I change the folder in the TreeView, the ObservableCollection is cleared and filled up again, which is automatically reflected in the the ListBox items.

    Here's the problem: The UI becomes unresponsive and it takes up to several seconds to update. Again, thumbnails do not have significance here (I tried disabling them). I think what takes the most time is the construction of 50-100 instances of my custom class, and their visual representation - it has to initialize an Image object for each one. But it's just my guess - could you please confirm or exclude the possibility?

    I'm beginning to think ObservableCollection may not the way to go here, since from what I read and a little from what I tried, there's no way to add items asynchronously, at least if these items are DependencyObjects. I tried creating my class instances with a BackgroundWorker and adding them to the collection in the ProgressChanged event handler, but it throws an exception (some threading vs dependencyobjects problem).

    Is there something that I'm missing? Or would I be better off by simply ditching the ObservableCollection and writing a good old async for loop to add the items?

  • oli.G
    oli.G over 11 years
    Thanks, I will try this out, and I'll definitely check out the interesting article, however I tried something similar (can't find it now) with no luck... I think it had a problem with my class being an DependencyObject. Something like "you can't create a dependencyobject on one thread and use it on another".
  • Rohit Vats
    Rohit Vats over 11 years
    Yeah your DP's have to be created on UI thread itself. In case you want to bind it to your UI, you have to use DP's but in case not, i would suggest to go for simple POCO properties implementing INPC interface.
  • oli.G
    oli.G over 11 years
    I do want to bind it... I need the listbox to display a list of my FILE class instances, with my custom datatemplate applied. I think I'll go with INPC.