2

这可能与阻塞的 UI 线程中的 ProgressBar 更新有关,但略有不同。

在对崩溃的 WinForms 控件(DevExpress 树列表)进行故障排除时,我们团队的一名成员遇到了不寻常的情况,我想知道是否有人可以帮助我们了解发生了什么。英语不是他的母语,所以我代表他发帖。

请参阅Visual Studio 2005 的此屏幕截图

请注意以下几点:

  1. 主 UI 线程已停止,当前处于 DevExpress 控件绘制方法中。

  2. 屏幕上显示的代码来自同一调用堆栈中较早的点。此代码位于数据层中,并被调用以响应控件请求为树节点显示图像的请求。(也许也源自 Paint 处理程序)

  3. 显示的代码来自调用堆栈的早期,在主 UI 线程上,当前正在等待锁定!由于远程系统可以发送在数据模型中的后台线程上处理的事件(即,数据模型在客户端和服务器之间同步),我们锁定以保持数据收集线程安全。

  4. 正如调用堆栈所示,我们继续在 UI 线程上处理绘制消息,而我们希望线程被阻塞。

这很难复制,我无法在我自己的盒子上使用更简单的测试项目来复制。然而,当这种情况出现时,结果是 DevExpress 控件的内部状态可能会混乱,导致控件崩溃。这看起来不像是控件中的错误,因为毫无疑问,它是在假设这些绘制方法仅在 UI 线程上运行的情况下编写的。我们在此处看到的内容使 UI 线程看起来像两个线程。

看起来这可能只是调用堆栈表示中的一个 Visual Studio 错误,除了这整个努力是为了解决已发布应用程序中控件偶尔崩溃的问题(在这种情况下,它显示为一个大UI 中的红色 X),因此问题似乎并非孤立于调试环境。

好吧,这很复杂,但希望是有道理的。有任何想法吗?

4

3 回答 3

3

我强烈建议不要锁定 UI 以等待后台处理。考虑类似多重缓冲的东西。您可以通过在 .NET 4 中使用线程安全集合来相当容易地获得这种行为,但如果这不是一个选项,那么在v4 之前发布的Parallel Extensions中就有这些版本。

于 2011-05-27T22:04:37.680 回答
0

我们在我们的项目中看到了类似的东西。堆栈跟踪看起来像是在 UI 线程等待锁定时调用了泵的事件循环。如果 Monitor.enter 在 UI 线程上调用时有一些特殊行为,则可能会发生这种情况。我相信这就是正在发生的事情,但我还没有找到任何文档来支持它。

可能与同步上下文有关:)

于 2011-06-30T13:14:27.347 回答
0

改变同步方案以使您不需要获取排他锁来读取数据怎么样?

在您可以确定读取将始终产生一致的数据的情况下,即使它发生在数据同时被写入的情况下,您也可以避免对 getter 没有锁定语句。否则有ReaderWriterLockSlim,它允许多个并发阅读器,但仍然允许您停止按下以进行写操作。

它不能解决所有问题,但至少可以减少死锁的机会。

于 2011-05-27T22:20:12.870 回答