[FIXED] How to make ObservableCollection thread-safe?

Issue

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

I am adding/removing from an ObservableCollection which is not on a UI thread.

I have a method names EnqueueReport to add to the colleciton and a DequeueReport to remove from the colleciton.

The flow of steps is as below :-

  1. 1.call EnqueueReport whenever a new report is requested
  2. call a method every few seconds to check if the report is generated (this has a foreach loop that checks the generated status of all reports in ObservableCollection)
  3. call DequeueReport if the report is generated

I am not much in C# libraries. Can someone please guide me on this?

Solution

You can create a simple thread friendly version of the observable collection. Like the following :

 public class MTObservableCollection<T> : ObservableCollection<T>
    {
        public override event NotifyCollectionChangedEventHandler CollectionChanged;
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            NotifyCollectionChangedEventHandler CollectionChanged = this.CollectionChanged;
            if (CollectionChanged != null)
                foreach (NotifyCollectionChangedEventHandler nh in CollectionChanged.GetInvocationList())
                {
                    DispatcherObject dispObj = nh.Target as DispatcherObject;
                    if (dispObj != null)
                    {
                        Dispatcher dispatcher = dispObj.Dispatcher;
                        if (dispatcher != null && !dispatcher.CheckAccess())
                        {
                            dispatcher.BeginInvoke(
                                (Action)(() => nh.Invoke(this,
                                    new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
                                DispatcherPriority.DataBind);
                            continue;
                        }
                    }
                    nh.Invoke(this, e);
                }
        }
    }

with that now do a massive find & replace and change all your ObservableCollection to MTObservableCollection and your good to go

Answered By – Franck

Answer Checked By – Gilberto Lyons (Easybugfix Admin)

Leave a Reply

(*) Required, Your email will not be published