操作通过LINQ to SQL查询更新这个ObservableCollection是否可以在单独的线程中执行,且是合理的?
如果是,那么在这种情况下,这个ObservableCollection实例是否是相同的?(我的意思是,如果从LINQ数据上下文中获取值的不是与向UI更新值的不是同一个ObservableCollection,则我将无法更新UI。)
.Net 4.5提供了一个解决方案,位于BindingOperations类中。
您现在可以使用BindingOperations.EnableCollectionSynchronization方法,如下所示:
private readonly object _personCollectionLock;
private ObservableCollection<Person> _personCollection;
public ObservableCollection<Person> PersonCollection
{
get { return _personCollection; }
set
{
_personCollection = value;
BindingOperations.EnableCollectionSynchronization(_personCollection, _personCollectionLock);
}
我只是在开发环境中尝试了一下,但现在当我从后台线程更新集合时,一切似乎都正常工作。
有一个更详细的解决方案讨论在这里:http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification
此方法的MSDN条目在这里:https://msdn.microsoft.com/en-us/library/system.windows.data.bindingoperations.enablecollectionsynchronization(v=vs.110).aspx
使用内置的ObservableCollection<T>
类,如果UI绑定到该集合,则无法从单独的线程更改其内容,它会抛出NotSupportedException
(但是集合项属性的更改通知可以正常工作)。我编写了一个AsyncObservableCollection<T>
类来处理这种情况。它通过在UI同步上下文中调用事件处理程序来实现。
我没有收到相同的System.NotSupportedException
,但不幸的是,如果我从另一个线程设置了我的ObservableCollectiony<MyType>
,我的UI没有正确更新。
对我有效的唯一方法是https://www.codeproject.com/Tips/1111432/Update-data-to-WPF-control-from-another-thread中提供的:
private SynchronizationContext _syncContext = SynchronizationContext.Current;
private ObservableCollection<PackageModel> _packageModelList;
public ObservableCollection<PackageModel> PackageModelList
{
get => _packageModelList;
set
{
if (_packageModelList == value)
return;
packageModelList = value;
RaisePropertyChanged("PackageModelList");
}
}
_syncContext.Send(x => { PackageModelList = OtherThreadPackageModels; },null);