0

I'm working wih an ObservableCollection in MultiThreading environment. Since ObservableCollection is not thread-safe I have to do my own syncronization using locks. So, When I have to read, write, or remove elements from the ObservableCollection I use lock

Also, since it is binding to UI, every updates to UI have to be done on MainThread. In WPF it seems that if you use BindingOperations.EnableCollectionSyncronization everythings is working well without explicitly calling MainThread, in Xamarin (Android) it seems that it doesn't work.

I would like to clarify if using EnableCollectionSyncronization needs also to use lock(as MS doc sais I think so), but I don't understand the different behaviours in WPF and Xamarin.

WPF

public class ExampleWPF{

    public Example(){
        var _lock = new Object();
        var _observableCollection = new ObservableCollection<string>();
        BindingOperations.EnableCollectionSyncronization(_observableCollection, _lock);
    }

    public void Add(){
        lock(_lock){
            _observableCollection.Add("Example");
        }
    }

    public void Search(){
        lock(_lock){
            _observableCollection.FirstOrDefault(x => x == "Example");
        }
    }
}

Xamarin

I have try also to quit explicit calling to MainThread on methods and calling it on ObservableCollectionCallback() but it seems that it doesn't work, the UI gets freezed but no exception is thrown.

public class ExampleXamarin{

    public Example(){
        var _lock = new Object();
        var _observableCollection = new ObservableCollection<string>();
        BindingBase.EnableCollectionSyncronization(_observableCollection, _lock, ObservableCollectionCallback);
    }

    private void ObservableCollectionCallback(ICollection collection, Object context, Action accessMethod, bool writeAccess){
        lock(context){
            accessMethod?.Invoke();
        }
    }

    public void Add(){
        lock(_lock){
            Device.BeginInvokeOnMainThread(() =>_observableCollection.Add("Example"));
        }
    }

    public void Remove(){
        lock(_lock){
            var iten = _observableCollection.FirstOrDefault(x => x == "Example");
            Device.BeginInvokeOnMainThread(() =>_observableCollection.Remove(item));
        }
    }

    public void Search(){
        lock(_lock){
            _observableCollection.FirstOrDefault(x => x == "Example");
        }
    }
}
JuanDYB
  • 590
  • 3
  • 9
  • 23
  • You don't need to call EnableCollectionSynchronization when you marshal the collection updates to the UI thread. Use either one or the other mechanism. – Clemens Aug 02 '22 at 13:58
  • I supuse you are talking about Xamarin. In WPF it seems that is working with EnableCollectionSynchronization, but in Xamarin not. I don't know why it isn't working on Xamarin. – JuanDYB Aug 02 '22 at 14:49
  • I assume that Xamarin is similar to WPF regarding the fact that you use *either* EnableCollectionSynchronization *or* Invoke, but not both at the same time. – Clemens Aug 02 '22 at 14:51
  • What do you want to say with "not at the same time". You mean the callback function? The method in Xamarin does not have the sign without Callback as WPF – JuanDYB Aug 02 '22 at 20:21
  • Not sure what exactly is so hard to understand. Either use EnableCollectionSynchronization and a lock object **or** marshal to the UI thread by an Invoke call. You don't need to use both mechanisms, as you are currently doing in ExampleXamarin. – Clemens Aug 02 '22 at 20:33

0 Answers0