Using BindingOperations.EnableCollectionSynchronization Using BindingOperations.EnableCollectionSynchronization multithreading multithreading

Using BindingOperations.EnableCollectionSynchronization


All the examples I've seen on Stack Overflow for this get it wrong. You must lock the collection when modifying it from another thread.

On dispatcher (UI) thread:

_itemsLock = new object();Items = new ObservableCollection<Item>();BindingOperations.EnableCollectionSynchronization(Items, _itemsLock);

Then from another thread:

lock (_itemsLock){    // Once locked, you can manipulate the collection safely from another thread    Items.Add(new Item());    Items.RemoveAt(0);}

More information in this article: http://10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux


I am not sure if this will help but still you can give it a try.

Add a Property in Debugger which will hold the Collection from BL like

private ObservableCollection<string> _data = new ObservableCollection<string>();private object _lock = new object();public ObservableCollection<string> Data { get {return _data;} }

In the constructor just add the below line

BindingOperations.EnableCollectionSynchronization(_data, _lock);

this will above line will take care of thread safety.

Below is the example

ViewModel (Debugger)

internal class ViewModelClass : INotifyPropertyChanged{    private object _lock = new object ();    private ObservableCollection<string> _data;    public ObservableCollection<string> Data    {        get { return _data; }        private set        {            _data = value;            RaisePropertyChanged ("Data");        }    }    private string _enteredText;    public string EnteredText    {        get { return _enteredText; }        set        {            _enteredText = value;            _data.Add (value); RaisePropertyChanged ("EnteredText");        }    }    private void RaisePropertyChanged (string name)    {        var pc = PropertyChanged;        if (pc != null)            pc (this, new PropertyChangedEventArgs (name));    }    public ViewModelClass ()    {        var _model = new ModelClass ();        Data = _model.Data;        _data.CollectionChanged += (s, e) => RaisePropertyChanged ("Data");    }    public event PropertyChangedEventHandler PropertyChanged;}

Model(BL)

internal class ModelClass{    private ObservableCollection<string> _data;    public ObservableCollection<string> Data    {        get { return _data; }        private set { _data = value; }    }    public ModelClass ()    {        _data = new ObservableCollection<string> { "Test1", "Test2", "Test3" };    }}

MainWindow.xaml.cs

public partial class MainWindow : Window{    public MainWindow ()    {        InitializeComponent ();        this.DataContext = new ViewModelClass ();    }}

MainWindow.xaml

<Window x:Class="CollectionSynchronizationTest.MainWindow"            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"            Title="MainWindow"            Height="350"            Width="525"><StackPanel>    <ComboBox IsEditable="True"                        ItemsSource="{Binding Data}"                        Text="{Binding EnteredText, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />    <Button Content="Test" /></StackPanel>

When the window loads just enter "SomeValue" in the ComboBox and then after pressing the Tab key you should find the new value in the ComboBox dropdown


A WPF application can display a collection of data using an ItemsControl or one of its subclasses (ListBox, DataGrid, TreeView, ListView, etc.). WPF channels all its access to the collection through a subclass of CollectionView. Both the ItemsControl and the CollectionView have affinity to the thread on which the ItemsControl was created, meaning that using them on a different thread is forbidden and throws an exception. In effect, this restriction applies to the collection as well. You may want to use the collection on multiple threads. For example, you want to update the collection (add or remove items) on a "data-gathering" thread, while displaying the results on a "user interface" thread, so that the UI remains responsive while data-gathering is happening. In such a situation, you are responsible for ensuring synchronized ("thread-safe") access to the collection. This is typically done using either a simple lock mechanism or a more elaborate synchronization mechanism such as semaphores, reset events, etc. While you must synchronize your application's access to the collection, you must also guarantee that access from WPF (specifically from CollectionView) participates in the same synchronization mechanism. You do this by calling the EnableCollectionSynchronization method.

The DOC remark this very nice, I think you should have a look:https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.bindingoperations.enablecollectionsynchronization?view=netcore-3.1