问题描述
|
这可能与被阻止的UI线程中的ProgressBar更新有关,但有些不同。
在对崩溃的WinForms控件(DevExpress树列表)进行故障排除时,我们团队的成员遇到了一种异常情况,我想知道是否有人可以帮助我们了解发生了什么。英语不是他的母语,所以我代表他发布信息。
请从Visual Studio 2005中查看此屏幕截图。
请注意以下几点:
UI主线程已停止,并且当前处于DevExpress控件的draw方法中。
屏幕上显示的代码来自同一调用堆栈中的较早位置。此代码在数据层中,并且响应于控件对显示给树节点的图像的请求而被调用。 (也许也源自Paint处理程序)
显示的代码来自主UI线程中调用栈中的早期代码,当前正在等待锁定!由于远程系统可以发送在数据模型中的后台线程上处理的事件(即,数据模型在客户端和服务器之间同步),因此我们锁定以确保数据收集线程的安全。
如调用堆栈所示,我们继续在UI线程上处理绘画消息,而我们希望该线程被阻塞。
这很难复制,我无法在自己的盒子上使用更简单的测试项目来复制。但是,当出现这种情况时,结果是DevExpress控件的内部状态可能会混乱,从而导致控件崩溃。这似乎并不是控件中的错误,因为毫无疑问,这些绘画方法仅在UI线程上运行,这是假定条件。我们在这里看到的结果看起来像UI线程就像两个线程。
似乎这只是调用堆栈表示中的Visual Studio错误,除了整个工作是由于对已发布应用中的控件偶尔崩溃进行了故障排除而导致的(这种情况下显示为很大) UI中的红色X),因此问题似乎并非仅在调试环境中存在。
好吧,这很复杂,但希望是有道理的。有任何想法吗?
解决方法
我强烈建议您不要锁定UI以等待后台处理。考虑类似多重缓冲的东西。您可以通过利用.NET 4中的线程安全集合来相当容易地获得这种行为,但是如果这不是一个选择,则在v4之前发布的Parallel Extensions中会有这些版本。
, 如何更改同步方案,以使您无需获取排他锁即可读取数据?
在可以确保即使在读取和写入数据的同时发生读取的情况下,也始终可以确保产生一致的数据的情况下,如果没有针对getter的lock语句,您也许可以摆脱困境。否则,有ReaderWriterLockSlim,它允许多个并发阅读器,但仍允许您停止按写操作。
它并不能解决所有问题,但至少可以减少死锁的机会。
, 我们在项目中看到了类似的东西。 UI线程正在等待锁时,堆栈跟踪看起来就像调用了泵的事件循环。如果在UI线程上调用Monitor.enter具有某些特殊行为,则可能会发生这种情况。我相信这是正在发生的事情,但是我还没有找到任何文档来对其进行备份。
可能与同步上下文有关:)