System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
Estoy agregando / eliminando de un ObservableCollection que no está en un subproceso de interfaz de usuario.
Tengo un método que nombra EnqueueReport para agregar a la colección y un DequeueReport para eliminar de la recostackción.
El flujo de pasos es el siguiente:
No estoy mucho en las bibliotecas de C #. ¿Puede alguien por favor guiarme en esto?
Puede crear una versión sencilla y amistosa de la colección observable. Como el siguiente:
public class MTObservableCollection : ObservableCollection { 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); } } }
con eso ahora haz un hallazgo masivo y reemplaza y cambia todo tu ObservableCollection
por MTObservableCollection
y listo.
La solución que Franck publicó aquí funcionará en el caso de que un hilo esté agregando cosas, pero ObservableCollection (y List, en el que se basa) no son seguros para subprocesos. Si hay varios hilos que escriben en la colección, podrían introducirse errores difíciles de rastrear. Escribí una versión de ObservableCollection que usa un ReaderWriteLockSlim para ser realmente seguro para subprocesos.
Lamentablemente, tocó el límite de caracteres de StackOverflow, por lo que aquí está en PasteBin. Esto debería funcionar al 100% con múltiples lectores / escritores. Al igual que regularmente con ObservableCollection, no es válido modificar la colección en una callback (en el hilo que recibió la callback).
A partir de .net framwork 4.5, puede usar la sincronización de colecciones nativas.
BindingOperations.EnableCollectionSynchronization(YourCollection, YourLockObject);
YourLockObject
es una instancia de cualquier objeto, por ejemplo, new Object();
. Usa uno por colección
Esto elimina la necesidad de una clase especial o algo. Solo habilita y disfruta;)
PD: BindingOperations
reside en Namespace System.Windows.Data
.
Puede usar una clase ObservableConcurrentCollection. Se encuentran en un paquete provisto por Microsoft en la biblioteca de Extras de Extensiones Paralelas.
Puede obtenerlo previamente creado por la comunidad en Nuget: https://www.nuget.org/packages/ParallelExtensionsExtras/
O consíguelo de Microsoft aquí: