0

我正在开发一个遗留应用程序,它到处都有 Application.DoEvents。我完全意识到,由于重入问题,这是不赞成的,但重构目前不是一种选择。

DoEvents 永远不会退出的问题已经开始出现。UI 是响应式的(我可以在用户日志中看到 UI 线程活动),因此 DoEvents 似乎正在发送消息,但由于某种原因它永远不会完成。不幸的是,这个 DoEvents 在主要的数据处理组件中,这意味着它会停止处理服务器响应,因为它卡在 DoEvents 行上。

我们有 Stopwatch 跟踪,它告诉 DoEvents 运行了多长时间 - 令人惊讶的是,我得到了一个日志,它说它运行了 188267770 毫秒,即 52 小时(gulp)。它似乎在星期六凌晨 3 点左右进入这种状态,直到用户在星期一进来并关闭应用程序(没有杀死进程,我可以看到 GUI 线程跟踪优雅地关闭事物),此时 DoEvents 完成并记录计时器数据(因此关闭期间发生的某些事情必须说服 DoEvents 完成)。

当然,这只发生在生产用户的机器上,而不是我的开发盒:)

有没有人见过类似的问题?

我已经反编译了 DoEvents 以及 Conrol.BeginInvoke 如何使用 Windows 消息队列将方法委托推送到 GUI 线程,但我看不到 DoEvents 如何像这样卡住,并保持 UI 响应。

源代码控制差异也不是一个选项,因为自用户拥有的最后一个“好”版本以来已经有大约 30 个版本,而这个新版本存在问题 - 所以大约 200 个文件已更改。

非常感谢保罗

4

2 回答 2

1

为了让循环继续运行,消息队列中必须有消息。所以我假设有一条消息在发送时会导致另一条消息被放入队列。以此类推,直到永远。

您是否有任何导致此类行为的后台处理?发布另一条消息以继续处理?系统中是否有可能发生的事件在处理后可以立即再次发生?

另一种选择是其中一条消息本身正在创建嵌套消息循环。例如,显示一个对话框会导致一个嵌套的消息循环,直到对话框被删除才会结束。您的应用程序是否会尝试显示一个对话框,然后由于某种原因不会被关闭?

鉴于可能性的数量,我们不可能告诉您答案。

于 2015-03-31T01:10:15.410 回答
1

经过大量挖掘,我终于找到了原因 - System.Windows.Forms.Timer。

基本上,两个或更多计时器可能导致 DoEvents() 调用永远不会结束。在处理一个计时器 WM_TIMER 消息时,另一个计时器可以发布其 WM_TIMER 消息,然后由 DoEvents 处理,因为正在处理第一个计时器将发布的消息,依此类推。

到目前为止,我正在开发的应用程序有大约 8 个计时器......

但实际上,DoEvents 是真正的罪魁祸首,所以我计划重新考虑以摆脱它。

于 2015-04-08T07:40:56.690 回答