当ListCollectionView监视Collection时,Dispatcher.Invoke挂起

时间:2009-12-29 15:02:33

标签: wpf multithreading dispatcher

我的问题与提到的in this post问题非常相似。本质上,Invoke挂起(仅在调试器外部运行时)。我认为这是由于Invoke调用的嵌套。

我正在使用MVVM Light,我尝试了两个多线程友好的ObservableCollection实现 - I've used this one for ages,最近尝试简化为this version。后者似乎更好,直到它失败了“拥有此线程”InvalidOperationException。看着我的前者副本,看起来我在那里吞咽异常。调皮顽皮。这将是财产改变“失败”的原因。

这是一个麻烦的操作流程。几乎在每一点上,我都尝试将内容移动到ui线程或将其移出ui线程。我设法推迟悬挂,但牺牲了财产改变了失败。

  • 请求从WCF上的线程进入主ViewModel
  • 解析请求(我已在后台线程上尝试并调用主线程)
  • 从数据库中检索ReportEntry对象
  • 显示通过Messenger请求编辑对话框发送到UI的消息。
  • 主窗口处理消息,调用IEditableObject.BeginEdit并显示编辑对话框。
  • 返回时,将调用Messenger回调操作。
  • 现在可以将ReportEntry添加到其正确的集合中。 MainViewModel有一个FileViewModel集合,每个集合都有一个ReportViewModel集合。
    • ReportViewModel通常由FileViewModel创建,用于观察FileModel集合的CollectionChanged事件。我试过绕过这个以避免更多的嵌套,但无济于事。

此时我的应用程序要么挂起(如果我主要在主线程上运行),要么由于线程而导致CollectionChanged事件失败,具体取决于我在线程之间移动的方式。

当应用程序挂起时,根据我附加的调试程序,它处于从Invoke调用的等待中。

哦,我已经尝试将各种Invoke更改为BeginInvoke的。

总结一下,我需要回答以下两个问题之一:

  1. 是什么让我的UI线程进入等待模式,以便Invoke挂起?
  2. 是否有更好的ObservableCollection派生类用于此目的?
  3. 感谢您的琢磨。

    更新

    好吧,我不知道是否删除这个问题并重新开始或者是什么。看来问题与我用来过滤ReportEntry的ListCollectionView有关。我的FileViewModel有一个

    public ListCollectionView FilteredReports {get; private set;}
    

    初始化如下:

    FilteredReports = new ListCollectionView(Reports);
    FilteredReports.Filter = FilterFunction;
    

    当我删除FilteredReports时,没有更多的悬挂。令人讨厌的是,我使用此视图作为ItemsSource的DataGrid位于DataTemplate中,因此将过滤器移动到我的视图也是非常重要的。那么,ListCollectionView在Collection更新上挂起的原因是什么?

2 个答案:

答案 0 :(得分:1)

而不是回答让我问。在“app hangs”场景中,您是否尝试过调试器下的“在异常为CLR异常时中断”选项?

是的,我仔细阅读了你的帖子,你说它没有悬挂在调试器下(Heisenbug)。只是想确保没有例外(甚至绑定或布局相关)。

我问这个是因为在非常罕见的情况下,我在WPF内部深处发现了死锁,当发生意外异常时(我认为它们是Mandelbugs)。修复该异常也解决了死锁问题。

答案 1 :(得分:0)

确保未在后台线程上创建ListCollectionView本身。我遇到了同样的问题,并在http://social.msdn.microsoft.com/Forums/en/wpf/thread/410a0b39-dfdb-4115-8a68-4ccabc17bcb6上找到了建议。我确实这样做,并确保在UI线程上构造ListCollectionView解决了我的“悬挂”问题。