如何从 .Net Standard 2.0 中的不同线程修改 ObservableCollection?

How to modify an ObservableCollection from a different thread in .Net Standard 2.0?

我在 .Net Standard 2.0 中有一个用于多个项目(Xamarin、WPF 等)的库,它使用 ObservableCollection 以便将它们绑定到 WPF 中或能够对它们的修改做出反应。

当我尝试从新线程的这些集合中删除元素时。然后它抛出一个 "NotSupportedException",通常使用 Dispatcher 来解析,从 UI 线程调用 remove 方法。

问题是 .Net Standard 不提供 Dispatcher(这是有道理的,因为可能没有 UI 线程)。所以这引出了我的问题;如何在没有 Dispatcher 的情况下从另一个线程修改这些集合?我是否在此处使用 ObservableCollections 做了一些我不应该做的事情?

异常:

System.NotSupportedException: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
à System.Windows.Data.CollectionView.OnCollectionChanged(Object sender,     NotifyCollectionChangedEventArgs args)
à System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
à ALX.GroundStation.Host.Infrastructure.ReadOnlyObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)

您可以简单地将适当的调度程序传递给库:

public void ThreadSafeAddItem(Item item, Dispatcher dispatcher)
{
    dispatcher.Invoke(()=> { AddItem(item); } );
}

但是由于 .Net 标准 2.0 没有 Dispatcher class 你需要一个委托来在 WPF 项目中做到这一点。

public event Action<Item> ItemAdded;
public void ThreadSafeAddItem(Item item)
{
    if(ItemAdded!=null) ItemAdded(item);
}

并且在您的 WPF 中:

 Library.ItemAdded += (item) => {
     Dispatcher.Invoke(()=>Library.ObservCollection.Add(item));
 };

在另一个线程中:

 Library.ThreadSafeAddItem(item);

Am I doing something that I shouldn't do by using ObservableCollections here

根据 MSDN:

To fully support transferring data values from binding source objects to binding targets, each object in your collection that supports bindable properties must implement an appropriate property changed notification mechanism such as the INotifyPropertyChanged interface.

这可能意味着每个可绑定的 属性 也需要这种机制,从而在您的应用中产生巨大的开销。

建议对库使用线程安全方法(如 POCO 模型),而不是在另一层(如 ViewModel)中处理这些绑定