一个简单的search for DoEvents
会带来很多结果,主要导致:
DoEvents
是邪恶的。不要使用它。改为使用线程。
一般引用的原因是:
但是TrackPopupMenu
和DoDragDrop
等一些值得注意的Win32函数会执行自己的消息处理,以保持用户界面的响应能力,就像DoEvents
一样。 />
然而,这些问题似乎都没有遇到过这些问题(表现,再入等等)。
他们是怎么做到的?他们如何避免DoEvents
引用的问题? (或做他们?)
答案 0 :(得分:27)
DoEvents()危险。但我敢打赌,你每天都会做很多危险的事情。就在昨天,我引爆了一些爆炸装置(未来的读者:请注意相对于某个美国假期的原始发布日期)。小心,我们有时可以解释危险。当然,这意味着要了解并了解危险是什么:
重新进入问题。这里实际上有两个危险:
性能问题。 DoEvents()可以提供多线程的幻觉,但它不是真正的多线程。这至少有三个真正的危险:
可用性问题。这些是由于未正确解释其他危险而导致的副作用。这里没有什么新东西,只要你适当地查看其他地方。
如果 你可以确定你已经考虑了所有这些事情,那就继续吧。但实际上,如果DoEvents()是您首先要解决的UI响应/更新问题,那么您可能无法正确解决所有这些问题。如果它不是你看的第一个地方,还有足够的其他选项,我会质疑你是如何考虑DoEvents()的。
现实情况是,大多数情况下,至少在.Net世界中, BackgroundWorker 组件几乎一样容易,至少在你做过一次或两次之后,它将以安全的方式完成工作。最近,异步/等待模式或Task
的使用可以更加有效和安全。
答案 1 :(得分:2)
回到16位Windows时代,当每个任务共享一个线程时,在紧密循环中保持程序响应的唯一方法是DoEvents
。这种非模态用法不支持线程。这是一个典型的例子:
' Process image
For y = 1 To height
For x = 1 to width
ProcessPixel x, y
End For
DoEvents ' <-- DON'T DO THIS -- just put the whole loop in another thread
End For
对于模态事物(例如跟踪弹出窗口),它可能仍然没问题。
答案 2 :(得分:2)
我可能错了,但在我看来,DoDragDrop
和TrackPopupMenu
是相当特殊的情况,因为它们接管了用户界面,因此没有重入问题(我认为是人们将DoEvents
描述为“邪恶”的主要原因。)
就我个人而言,我不认为将某个功能视为“邪恶”是有帮助的 - 而是解释陷阱,以便人们可以自行决定。在DoEvents
的情况下,在极少数情况下使用它仍然是合理的,例如在显示模态进度对话框时,用户无法与UI的其余部分进行交互,因此没有引入问题。
当然,如果“邪恶”是指“在没有完全理解陷阱的情况下你不应该使用的东西”,那么我同意DoEvents
是邪恶的。