Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does EnableCollectionSynchronization work?

There are several posts that explain the usage of BindingOperations.EnableCollectionSynchronization. E.g. BindingOperations.EnableCollectionSynchronization mystery in WPF or Using BindingOperations.EnableCollectionSynchronization

However, my understanding of a "lock" does not match the behavior of the following demonstration.

private void Button_Click(object sender, RoutedEventArgs e)
{
    var itemsLock = new object();
    var items = new ObservableCollection<string>();
    BindingOperations.EnableCollectionSynchronization(items, itemsLock);

    Task.Run(() =>
    {
        lock (itemsLock)
        {
            Debug.WriteLine("task inside lock");
            Thread.Sleep(5000);
            items.Where(m => m == "foo").ToArray();
        }
        Debug.WriteLine("task outside lock");
    });

    Thread.Sleep(1000);
    Debug.WriteLine("UI thread add..");
    items.Add("foo");
    Debug.WriteLine("UI thread add..done");
}

Due to the lock, I expected Debug Output like this:

task inside lock
UI thread add..
task outside lock
UI thread add..done

But I find an Debug Output like this:

task inside lock
UI thread add..
UI thread add..done
task outside lock

Background info: I occasionally experience InvalidOperationExceptions "collection was modified" when running LINQ queries on a frequently changed ObservableCollection. This lead me to breaking it down to the previous sample. Then I found that my assumption of how EnableCollectionSynchronization works is wrong.

like image 409
sa.he Avatar asked Jan 22 '26 22:01

sa.he


1 Answers

You should synchronize all access to the collection using the same lock, i.e. you should lock around the call to Add:

lock (itemsLock)
    items.Add("foo");

The documentation is pretty clear on this:

To use a collection on multiple threads, one of which is the UI thread that owns the ItemsControl, an application has the following responsibilities:

  • Choose a synchronization mechanism.
  • Synchronize all access from the application to the collection using that mechanism.
  • Call EnableCollectionSynchronization to inform WPF of the mechanism.
  • ...
like image 118
mm8 Avatar answered Jan 25 '26 11:01

mm8



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!