这可能与ProgressBar updates in blocked UI thread有关,但有点不同。
在对崩溃的WinForms控件(DevExpress treelist)进行故障排除时,我们团队的一名成员遇到了异常情况,我想知道是否有人可以帮助我们了解正在发生的事情。英语不是他的第一语言,所以我代表他发帖。
请参阅Visual Studio 2005中的this screenshot。
请注意以下几点:
主UI线程已停止,目前处于DevExpress控件绘制方法中。
屏幕上显示的代码来自同一个调用堆栈中较早的一个点。此代码位于数据层中,并且响应控件对树节点显示图像的请求而调用。 (也许也来自Paint处理程序)
显示的代码来自callstack中较早的主UI线程,并且当前正在等待锁定!由于远程系统可以发送在数据模型中的后台线程上处理的事件(即,数据模型在客户端和服务器之间同步),因此我们锁定以保持数据收集线程安全。
正如callstack所示,我们继续在UI线程上处理绘制消息,而我们希望线程被阻止。
这很难复制,而且我无法在自己的盒子上使用更简单的测试项目。然而,当出现这种情况时,结果是DevExpress控件的内部状态可能会混乱,导致控件崩溃。这看起来并不像是控件中的错误,因为毫无疑问,假设这些绘制方法仅在UI线程上运行。我们在这里看到的内容使得UI线程看起来像两个线程。
这似乎可能只是在callstack的呈现中只是一个Visual Studio错误,除了这整个努力是由于努力解决在发布的应用程序中偶尔崩溃的控件(在这种情况下它显示作为UI中的一个大红色X,所以看起来问题并没有与调试环境隔离。
好吧,这很复杂,但希望有道理。有什么想法吗?
答案 0 :(得分:3)
我强烈建议反对锁定用户界面以等待后台处理。考虑multiple buffering之类的内容。您可以通过在.NET 4中使用thread-safe collections来相当轻松地获得此行为,但如果这不是一个选项,则在v4之前发布Parallel Extensions中的版本。
答案 1 :(得分:0)
如何更改同步方案,以便您不需要获取独占锁来读取数据?
在您可以确定读取将始终产生一致数据的情况下,即使在数据也被写入时也会发生这种情况,您可能无法获得getter的锁定语句。否则有ReaderWriterLockSlim,它允许多个并发读取器但仍允许您停止按下进行写入操作。
它并不能解决所有问题,但它确实至少减少了死锁的机会。
答案 2 :(得分:0)
我们在项目中看到类似的东西。堆栈跟踪看起来像在UI线程等待锁定时调用泵的事件循环。如果Monitor.enter在UI线程上调用时有一些特殊行为,则可能会发生这种情况。我相信这就是正在发生的事情,但我还没有找到任何支持它的文件。
可能与同步上下文有关:)