C# 优雅地处理需要在调度程序线程上进行更改的集合更改

C# 优雅地处理需要在调度程序线程上进行更改的集合更改,c#,.net,wpf,mvvm-light,dispatcher,C#,.net,Wpf,Mvvm Light,Dispatcher,我的情况如下: 我从ListCollectionView中获取了一个用户界面项控件“ResultsPresenter”(WPF),该ListCollectionView使用非UserInterface类中的BindingList“Results”作为ListCollectionView.Source属性 每当我对“结果”进行更改(如添加操作)时,我都会得到一个NotSupportedException,坚持认为{“这种类型的CollectionView不支持从与Dispatcher线程不同的线程

我的情况如下:

我从ListCollectionView中获取了一个用户界面项控件“ResultsPresenter”(WPF),该ListCollectionView使用非UserInterface类中的BindingList“Results”作为ListCollectionView.Source属性

每当我对“结果”进行更改(如添加操作)时,我都会得到一个NotSupportedException,坚持认为{“这种类型的CollectionView不支持从与Dispatcher线程不同的线程对其SourceCollection进行更改。”}

看起来这个错误似乎来自“Results”集合,但是错误信息显然是WPF生成的。我想知道我为什么抛出这个错误,以及如何在不向WPF相关代码公开包含“结果”的类的情况下解决它

注:


此解决方案是在直接查看绑定的“Results”属性时导致此错误之后产生的,ListCollectionView的引入只是为了尝试纠正这种情况,很可能不是问题的一部分。

结果集合引发的事件由
ListCollectionView处理,以通知UI。如果这种情况发生在非UI线程上,则会出现此异常


因此,您永远不应该从非UI线程修改UI绑定集合,除非它明确支持它。不久前,我编写了这样一个支持它的类,您可以找到它。

自从WPF被称为Avalon以来,这一直是集合更改通知的一个已知问题。关于这个问题,请参见


通过在dispatcher线程上进行集合更改,您可以非常轻松地解决这个问题。因为我猜您有一个长时间运行的操作返回项目或更改,所以我建议查看并使用IObservable的ObserveOnDispatcher设置。总的来说,这类事情比过去容易多了

然而,这个问题在引入ListCollectionView之前就存在了,所以要么是同一个问题以不同的方式表现出来,要么是另一个问题。我不是100%熟悉这个错误或者如何解决它。你说的“在引入ListCollectionView之前”是什么意思?您是否直接绑定到集合?在这种情况下,一个CollectionView是由WPF隐式创建的,因此它最终与您当前的情况相同,这就是发生的情况。话虽如此,我能做些什么来解决这个问题?我是否应该使用事件并将目标集合包装在代理集合中,代理集合在UI线程上执行其所有更新?请尝试使用MVVM Light Toolkit中的DispatcherHelper类进行调用以修改集合。@firoso,您是否查看了我发布的链接?如果您使用该集合而不是普通的ObservableCollection,is将在dispatcher上引发CollectionChanged事件threadRx似乎不是一个适用的解决方案。在这种情况下,无论哪种方式,如果您不能通过用户界面以外的其他方式更新集合,我都不明白绑定到集合有什么意义。在不依赖第三方库或破坏封装的情况下,是否有一个已知的最佳实践来解决此问题?Rx是第一方库(由Microsoft制造)。只要在UI线程上运行,就可以在任何程序集中更新集合。在实践中,这很少会导致问题,这就是为什么他们仍然没有抽出时间来解决这个问题。