ListCollectionView 监控 Collection 时 Dispatcher.Invoke 挂起

发布于 2024-08-16 10:36:23 字数 2420 浏览 10 评论 0 原文

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

我正在使用 MVVM Light,并且尝试了多线程友好的 ObservableCollection 的两种实现 - 我已经使用这个很久了,最近尝试简化为 此版本。后者似乎更好,直到它因“由该线程拥有”InvalidOperationException 而失败。看看我的前者副本,看起来我正在吞下其中的异常。顽皮顽皮。这就是物业变更“失败”的原因。

下面是比较麻烦的操作流程。几乎在每一点上,我都尝试过将事物移至 ui 线程或将它们移出 ui 线程。我设法推迟了绞刑,但代价是财产改变失败。

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

此时,我的应用程序要么挂起(如果我主要在主线程上操作),要么 CollectionChanged 事件因线程而失败,具体取决于我如何在线程之间移动内容。

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

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

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

  1. 是什么使我的 UI 线程进入等待模式,导致 Invoke 挂起?
  2. 是否有更好的 ObservableCollection 派生类可用于此目的?

感谢您的思考。

更新

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

public ListCollectionView FilteredReports {get; private set;}

初始化,如下所示:

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

当我删除 FilteredReports 时,不再有挂起。令人烦恼的是,我使用此视图作为 ItemsSource 的 DataGrid 位于 DataTemplate 中,因此将过滤器移动到我的视图也并非易事。那么,ListCollectionView 有什么理由挂在集合更新上吗?

My problem feels very similar to the issue mentioned in this post. Essentially, Invoke is hanging (only when run outside the debugger). I think it's due to nesting of Invoke calls.

I'm using MVVM Light, and I've tried two implementations of a multi-thread friendly ObservableCollection - I've used this one for ages and recently tried to simplify to this version. The latter seemed better until it failed with a "owned by this thread" InvalidOperationException. And looking at my copy of the former, looks like I'm swallowing exceptions in there. Naughty naughty. This would be the reason for the property changed "failures".

Here is the flow of operation that is troublesome. At nearly every point, I've tried moving things to the ui thread or moving them off the ui thread. I have managed to defer hanging, but at the expense of property changed failures.

  • Request comes in from thread over WCF to primary ViewModel
  • Request is parsed (I've tried both on the background thread and invoking to the main thread)
  • ReportEntry object is retrieved from database
  • Message sent to UI through Messenger requesting edit dialog be shown.
  • Main Window handles message, IEditableObject.BeginEdit is called and the edit dialog is shown.
  • Upon return the Messenger callback Action is called.
  • The ReportEntry is now ready to be added to its proper collection. MainViewModel has a collection of FileViewModels which each have a collection of ReportViewModels.
    • The ReportViewModels are usually created by the FileViewModel watching the FileModel's collection's CollectionChanged events. I've tried bypassing this to avoid more nesting, to no avail.

It is at this point that my app either hangs (if I'm operating primarily on the main thread) or CollectionChanged events fail due to threading, depending on how I've moved things between threads.

When the app hangs, it is in a wait called from Invoke, according to the debugger I attach.

Oh and I've tried changing various Invoke's to BeginInvoke's.

To summarize I need an answer to one of these two questions:

  1. What puts my UI thread into a wait mode such that Invoke is hanging?
  2. Is there a better ObservableCollection-derived class to use for this?

Thanks for pondering.

UPDATE

Well, I don't know whether to delete this question and start over or what. It appears the problem is tied to a ListCollectionView I was using to filter the ReportEntry's. My FileViewModel has a

public ListCollectionView FilteredReports {get; private set;}

initialized like so:

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

When I remove FilteredReports, there is no more hanging. Annoyingly, the DataGrid I'm using this view as the ItemsSource for is in a DataTemplate, so moving the filter to my view is non-trivial as well. So, any reason for ListCollectionView to be hanging on Collection updates?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

可是我不能没有你 2024-08-23 10:36:23

我不回答,而是问。在“应用程序挂起”场景中,您是否尝试过调试器下的“当异常为 CLR 异常时中断”选项?

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

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

Instead of answering let me ask. In the "app hangs" scenario, have you tried "Break when an exception is CLR exception" option under debugger?

Yes, I read your post carefully, you said it is not hanging under debugger (Heisenbug). Just want to be sure there are no exceptions (even binding or layout related).

I'm asking this because in very rare scenarios, I've seen deadlocks deep in WPF internals, when unexpected exception occurs (I considered them as Mandelbugs). And fixing that exception also fixed deadlock problem.

后知后觉 2024-08-23 10:36:23

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

Make sure that your ListCollectionView itself isn't being created on a background thread. I had this same problem and found that advice on http://social.msdn.microsoft.com/Forums/en/wpf/thread/410a0b39-dfdb-4115-8a68-4ccabc17bcb6. I indeed was doing that and making sure that the ListCollectionView was constructed on the UI thread solved my "hanging" problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文