我的问题感觉与这篇文章中提到的问题非常相似。本质上,Invoke 是挂起的(仅当在调试器之外运行时)。我认为这是由于 Invoke 调用的嵌套。
我正在使用 MVVM Light,并且我已经尝试了多线程友好的 ObservableCollection 的两种实现——我已经使用这个很久了,最近尝试简化到这个版本。后者似乎更好,直到它因“由该线程拥有”InvalidOperationException 而失败。看着我的前者副本,看起来我在那里吞下了异常。调皮调皮。这将是属性更改“失败”的原因。
这是麻烦的操作流程。几乎在每一点,我都尝试过将东西移到 ui 线程或将它们移出 ui 线程。我设法推迟挂起,但以财产变更失败为代价。
- 请求来自 WCF 上的线程到主 ViewModel
- 请求被解析(我在后台线程和调用主线程都试过)
- 从数据库中检索 ReportEntry 对象
- 显示通过 Messenger 请求编辑对话框发送到 UI 的消息。
- 主窗口处理消息,调用 IEditableObject.BeginEdit 并显示编辑对话框。
- 返回时调用 Messenger 回调 Action。
- 现在可以将 ReportEntry 添加到其适当的集合中。MainViewModel 有一个 FileViewModel 的集合,每个 FileViewModel 都有一个 ReportViewModel 的集合。
- ReportViewModels 通常由 FileViewModel 监视 FileModel 的集合的 CollectionChanged 事件创建。我试过绕过这个以避免更多的嵌套,但无济于事。
正是在这一点上,我的应用程序要么挂起(如果我主要在主线程上操作),要么 CollectionChanged 事件由于线程而失败,这取决于我在线程之间移动事物的方式。
根据我附加的调试器,当应用程序挂起时,它处于从 Invoke 调用的等待状态。
哦,我已经尝试将各种 Invoke 更改为 BeginInvoke。
总而言之,我需要回答以下两个问题之一:
- 是什么让我的 UI 线程进入等待模式,使得 Invoke 挂起?
- 是否有更好的 ObservableCollection 派生类用于此?
谢谢你的思考。
更新
好吧,我不知道是否删除这个问题并重新开始或什么。看来问题与我用来过滤 ReportEntry 的 ListCollectionView 有关。我的 FileViewModel 有一个
public ListCollectionView FilteredReports {get; private set;}
像这样初始化:
FilteredReports = new ListCollectionView(Reports);
FilteredReports.Filter = FilterFunction;
当我删除 FilteredReports 时,不再挂起。烦人的是,我将此视图用作 ItemsSource 的 DataGrid 位于 DataTemplate 中,因此将过滤器移至我的视图也并非易事。那么,ListCollectionView 有什么理由挂在 Collection 更新上?