我正在研究遗留的应用程序,其中包含了Application.DoEvents。我完全清楚,由于重新引入问题,这是不赞成的,但重新保理目前不是一种选择。
DoEvents永不退出的问题已经开始发生。 UI是响应式的(我可以在用户日志中看到UI线程活动),因此DoEvents似乎在抽取消息,但由于某种原因它永远不会完成。不幸的是,这个DoEvents位于主数据处理组件中,这意味着它会停止处理服务器响应,因为它停留在DoEvents行上。
我们有秒表跟踪,它告诉DoEvents运行了多长时间 - 我得到了一个日志,据说它运行的时间为188267770毫秒,即52小时(gulp)。它似乎在星期六凌晨3点左右进入这种状态,直到用户星期一进来并关闭应用程序(不杀死进程,我可以看到GUI线程跟踪优雅地关闭事物),此时DoEvents完成并记录计时器数据(因此在关机期间发生的事情必须说服DoEvents完成)。
当然,这只发生在生产用户的机器上,而不是在我的开发箱上:)
有没有人见过类似的问题?
我已经反编译DoEvents以及Conrol.BeginInvoke如何使用Windows消息队列将方法委托推送到GUI线程,但我看不出DoEvents如何像这样被卡住,并保持UI响应。
源代码控制差异也不是一个选项,因为自用户上一个“好”版本以来已有大约30个版本,而这个新版本存在问题 - 所以大约有200个文件发生了变化。
非常感谢 保罗
答案 0 :(得分:1)
要使循环继续运行,消息队列上必须有消息。所以我假设有一条消息,当调度时,会导致另一条消息被放入队列。等等永远。
您是否有导致此类行为的后台处理?发布另一条消息以继续处理?系统中是否存在可能发生的事件,处理后可能会立即再次发生?
另一种选择是其中一条消息本身就是创建一个嵌套的消息循环。例如,显示一个对话框会导致嵌套的消息循环在删除对话框之前无法完成。您的应用是否尝试显示一个对话框,然后由于某种原因不会被解雇?
考虑到可能性的数量,我们无法告诉你答案。
答案 1 :(得分:1)
经过多次挖掘后,我终于找到了原因--System.Windows.Forms.Timer。
基本上两个或多个计时器可能导致DoEvents()调用永不结束。在处理一个定时器WM_TIMER消息时,另一个定时器可以发布其WM_TIMER消息,然后由DoEvents处理,因为正在处理第一个Timer将发布,等等。
我正在开发的应用程序到目前为止已经发现了大约8个计时器......
但实际上,DoEvents是真正的罪魁祸首所以我打算重新考虑它以摆脱它。