在C#中可以使用Application.DoEvents()吗?
这个函数是不是可以让图形用户界面跟上应用程序的其他部分,就像vb6的DoEvents一样?
发布于 2011-03-22 10:47:20
根据我的经验,我建议在.NET中使用DoEvents时要非常谨慎,在包含DataGridViews的TabControl中使用DoEvents时,我遇到了一些非常奇怪的结果。另一方面,如果您正在处理的只是一个带有进度条的小表单,那么它可能是可以的。
底线是:如果您要使用DoEvents,那么在部署应用程序之前,您需要对其进行彻底的测试。
发布于 2011-03-04 00:35:11
Hmya,DoEvents()的持久神秘感。它受到了巨大的反对,但没有人真正解释为什么它是“坏的”。和“不要改变结构”一样的智慧。呃,为什么运行库和语言支持结构的变异,如果这很糟糕的话?同样的原因:如果你做得不对,你就会搬起石头砸自己的脚。很容易。要做好这件事,需要确切地知道它做了什么,对于DoEvents()来说,这绝对不容易理解。
立刻:几乎所有的Windows Forms程序实际上都包含对DoEvents()的调用。不过,它被巧妙地伪装起来,使用了一个不同的名称: ShowDialog()。DoEvents()允许对话框是模态的,而不会冻结应用程序中的其余窗口。
大多数程序员在编写自己的模式循环时,都希望使用DoEvents来防止用户界面冻结。它当然可以做到这一点;它会发送Windows消息,并将所有绘制请求都发送出去。然而,问题是它不是有选择性的。它不仅发送paint消息,还发送其他所有内容。
而且有一组会引起麻烦的通知。它们来自显示器前面大约3英尺的地方。例如,用户可以在调用DoEvents()的循环运行时关闭主窗口。这样的话,用户界面就没了。但是你的代码并没有停止,它仍然在执行循环。那可不好。非常非常糟糕。
还有更多:用户可以单击相同的菜单项或按钮,从而启动相同的循环。现在,您有两个执行DoEvents()的嵌套循环,前一个循环被挂起,新的循环从头开始。这可能行得通,但机会很小。尤其是当嵌套循环结束,挂起的循环重新开始,试图完成已经完成的作业时。如果这不是一个异常的炸弹,那么肯定是所有的数据都被打乱了。
返回到ShowDialog()。它执行DoEvents(),但请注意,它还做了其他事情。它禁用应用程序中除对话框之外的所有窗口。现在3英尺的问题已经解决了,用户不能做任何事情来扰乱逻辑。同时解决了关闭窗口和重新开始作业的故障模式。或者换一种说法,用户没有办法让你的程序以不同的顺序运行代码。它将以可预测的方式执行,就像您测试代码时一样。这使得对话框非常烦人;谁不讨厌对话框处于活动状态,并且不能从另一个窗口复制和粘贴内容?但这就是代价。
这就是在您的代码中安全地使用DoEvents所需要的。将所有窗体的Enabled属性设置为false是避免问题的一种快速有效的方法。当然,没有程序员真正喜欢这样做。这就是为什么你不应该使用DoEvents()。你应该使用线程。即使他们给了你一个完整的武器库,以丰富多彩和令人费解的方式射杀你的脚。但好处是你只会射伤自己的脚;它(通常)不会让用户射伤自己的脚。
C#和VB.NET的下一个版本将使用新的await和async关键字提供不同的配置。这在很小程度上受到了DoEvents和线程带来的麻烦的启发,但在很大程度上是受到了WinRT设计的启发,该设计要求您在异步操作发生时保持UI更新。就像从文件中读取一样。
发布于 2011-03-03 22:10:15
它可以是,但它是一个黑客。
参见。
直接从thedev引用的the MSDN page:
调用此方法会导致在处理所有等待的窗口消息时挂起当前线程。如果消息导致触发事件,则应用程序代码的其他部分可能会执行。这可能会导致应用程序表现出难以调试的意外行为。如果执行耗时较长的操作或计算,则通常更可取的做法是在新线程上执行这些操作。有关异步编程的更多信息,请参见异步编程概述。
因此,微软告诫不要使用它。
此外,我认为它是一个黑客,因为它的行为是不可预测的,并且容易产生副作用(这来自于尝试使用DoEvents而不是旋转新线程或使用后台工作程序的经验)。
这里没有男子汉气概-如果它是一个健壮的解决方案,我会全力以赴。然而,尝试在.NET中使用DoEvents只会给我带来痛苦。
https://stackoverflow.com/questions/5181777
复制相似问题