Come rendere ObservableCollection thread-safe?

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

Sto aggiungendo / rimuovendo da un ObservableCollection che non è su un thread dell’interfaccia utente.

Ho un metodo nomi EnqueueReport da aggiungere alla raccolta e un DequeueReport da rimuovere dalla raccolta.

Il stream di passaggi è come di seguito: –

  1. 1.call EnqueueReport ogni volta che viene richiesto un nuovo report
  2. chiamare un metodo ogni pochi secondi per verificare se il report è stato generato (questo ha un ciclo foreach che controlla lo stato generato di tutti i report in ObservableCollection)
  3. chiamare DequeueReport se il report è stato generato

Non sono molto nelle librerie C #. Qualcuno può guidarmi per favore su questo?

Puoi creare una semplice versione thread friendly della collezione osservabile. Mi piace il seguente:

  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 quello ora fai un enorme ritrovamento e sostituisci e cambia tutta la tua ObservableCollection in MTObservableCollection e il tuo bene per andare

La soluzione che Franck ha postato qui funzionerà nel caso in cui un thread aggiunga delle cose, ma ObservableCollection stesso (e List, su cui è basato) non sono thread-safe. Se più thread stanno scrivendo alla raccolta, potrebbero essere introdotti bug difficili da rintracciare. Ho scritto una versione di ObservableCollection che utilizza un ReaderWriteLockSlim per essere veramente thread-safe.

Sfortunatamente, ha colpito il limite di caratteri StackOverflow, quindi eccolo in PasteBin. Questo dovrebbe funzionare al 100% con più lettori / scrittori. Proprio come ObservableCollection, non è valido modificare la raccolta in una richiamata da essa (sul thread che ha ricevuto la richiamata).

A partire da .net framwork 4.5 è ansible utilizzare la sincronizzazione della collezione nativa.

BindingOperations.EnableCollectionSynchronization(YourCollection, YourLockObject);

YourLockObject è un’istanza di qualsiasi object, ad esempio new Object(); . Usane uno per collezione.

Questo elimina la necessità di alcune classi speciali o altro. Basta abilitare e divertirsi;)

PS: BindingOperations risiede in Namespace System.Windows.Data .

È ansible utilizzare una class ObservableConcurrentCollection. Si trovano in un pacchetto fornito da Microsoft nella libreria Parallel Extensions Extras.

Puoi ottenerlo precostruito dalla comunità su Nuget: https://www.nuget.org/packages/ParallelExtensionsExtras/

O prendilo da Microsoft qui:

https://code.msdn.microsoft.com/ParExtSamples