Как сделать ObservableCollection потокобезопасным?
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
Я добавляю / удаляю из ObservableCollection, который не находится в потоке пользовательского интерфейса.
У меня есть имена методов EnqueueReport для добавления в colleciton и DequeueReport для удаления из colleciton.
поток шагов, как показано ниже : -
- 1.EnqueueReport звонят, когда новый доклад
- вызовите метод каждые несколько секунд, чтобы проверить, сгенерирован ли отчет (это имеет цикл foreach, который проверяет сгенерированный состояние всех отчетов в ObservableCollection)
- вызовите DequeueReport, если отчет генерируется
Я не очень много в библиотеках c#. Кто-нибудь может мне помочь?
4 ответов
вы можете создать простой поток дружественной версии наблюдаемой коллекции. Например:
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);
}
}
}
С этим теперь сделайте массивную находку и замените и измените все свои ObservableCollection
to MTObservableCollection
и ваш хорошо идти
решение, которое Франк разместил здесь, будет работать в случае, когда один поток добавляет вещи, но сам ObservableCollection (и список, на котором он основан) не являются потокобезопасными. Если в коллекцию записывается несколько потоков,могут быть введены труднодоступные ошибки. Я написал версию ObservableCollection, которая использует ReaderWriteLockSlim, чтобы быть действительно потокобезопасной.
к сожалению, он попал в предел символов StackOverflow, поэтому здесь он находится на PasteBin. Это должно работать 100% с несколькими читателями / писателями. Как и обычная ObservableCollection, недопустимо изменять коллекцию в обратном вызове из нее (в потоке, который получил обратный вызов).
начиная с .net framwork 4.5 вы можете использовать собственную синхронизацию коллекции.
BindingOperations.EnableCollectionSynchronization(YourCollection, YourLockObject);
YourLockObject
является экземпляром любого объекта, например new Object();
. Используйте по одному на коллекцию.
это исключает потребность некоторого особенного класса или что-нибудь. Просто включите и наслаждайтесь ;)
PS:BindingOperations
находится в пространстве имен System.Windows.Data
.
можно использовать класс ObservableConcurrentCollection. Они находятся в пакете, предоставленном Microsoft в библиотеке параллельных расширений Extras.
вы можете получить его предварительно построенным сообществом на Nuget: https://www.nuget.org/packages/ParallelExtensionsExtras/
или получить его от Microsoft здесь: