Is there a Threadsafe Observable collection in .NET 4?

前端 未结 4 1768
南方客
南方客 2020-12-03 01:45

Platform: WPF, .NET 4.0, C# 4.0

Problem: In the Mainwindow.xaml i have a ListBox bound to a Customer collection which is currently an ObservableCollecti

4条回答
  •  刺人心
    刺人心 (楼主)
    2020-12-03 01:48

    I spent ages looking at all the solutions and none really fit what I needed, until I finally realized the problem: I didn't want a threadsafe list - I just wanted a non-threadsafe list that could be modified on any thread, but that notified changes on the UI thread.

    (The reason for not wanting a threadsafe collection is the usual one - often you need to perform multiple operations, like "if it's not in the list, then add it" which threadsafe lists don't actually help with, so you want to control the locking yourself).

    The solution turned out to be quite simple in concept and has worked well for me. Just create a new list class that implements IList and INotifyCollectionChanged. Delegate all calls you need to an underlying implementation (e.g. a List) and then call notifications on the UI thread where needed.

    public class AlbumList : IList, INotifyCollectionChanged
    {
        private readonly IList _listImplementation = new List();
    
        public event NotifyCollectionChangedEventHandler CollectionChanged;
    
        private void OnChanged(NotifyCollectionChangedEventArgs e)
        {
            Application.Current?.Dispatcher.Invoke(DispatcherPriority.Render, 
                         new Action(() => CollectionChanged?.Invoke(this, e)));
        }
    
        public void Add(Album item)
        {
            _listImplementation.Add(item);
            OnChanged(new NotifyCollectionChangedEventArgs(
                          NotifyCollectionChangedAction.Add, item));
        }
    
        public bool Remove(Album item)
        {
            int index = _listImplementation.IndexOf(item);
            var removed = index >= 0;
            if (removed)
            {
                _listImplementation.RemoveAt(index);
                OnChanged(new NotifyCollectionChangedEventArgs(
                              NotifyCollectionChangedAction.Remove, item, index));
            }
            return removed;
        }
        // ...snip...
    }
    

提交回复
热议问题