Cra*_*ton 263 c# doevents winforms
可以Application.DoEvents()在C#中使用吗?
这个函数是否能够让GUI跟上应用程序的其余部分,就像VB6 DoEvents一样?
Han*_*ant 458
Hmya,DoEvents()的持久神秘感.对它有强烈的反对意见,但没有人真正解释为什么它"糟糕".与"不要改变结构"相同的智慧.嗯,为什么运行时和语言支持变异结构,如果那么糟糕?同样的道理:如果你做得不对,你会在脚下射击.容易.做正确的事情需要确切知道它的作用,在DoEvents()的情况下,这绝对不容易理解.
马上就是:几乎任何Windows窗体程序实际上都包含对DoEvents()的调用.它巧妙地伪装,但使用不同的名称:ShowDialog().DoEvents()允许对话框是模态的,而不会冻结应用程序中的其余窗口.
大多数程序员希望在编写自己的模态循环时使用DoEvents来阻止用户界面冻结.当然这样做; 它调度Windows消息并获取任何绘制请求.但问题是它没有选择性.它不仅可以发送绘制消息,还可以提供其他所有内容.
并且有一组导致麻烦的通知.它们来自显示器前方约3英尺处.例如,当调用DoEvents()的循环正在运行时,用户可以关闭主窗口.这工作,用户界面消失了.但是你的代码没有停止,它仍在执行循环.那很糟.非常非常糟糕.
还有更多:用户可以单击导致相同循环开始的相同菜单项或按钮.现在你有两个执行DoEvents()的嵌套循环,前一个循环被挂起,新循环从头开始.这可行,但男孩的可能性很小.特别是当嵌套循环结束并且暂停的循环重新开始时,尝试完成已完成的作业.如果没有异常爆炸,那么数据肯定会被打乱.
回到ShowDialog().它执行DoEvents(),但请注意它执行其他操作.它会禁用应用程序中的所有窗口,而不是对话框.现在解决了3英尺的问题,用户无法做任何事情来搞乱逻辑.关闭窗口和启动作业再次失败模式都得到了解决.或者换句话说,用户无法使程序以不同的顺序运行代码.它将以可预测的方式执行,就像测试代码时一样.它使对话非常烦人; 谁不讨厌激活对话而无法从另一个窗口复制和粘贴东西?但那就是价格.
这是在代码中安全使用DoEvents所需的.将所有表单的Enabled属性设置为false是避免问题的快速有效方法.当然,没有程序员真正喜欢这样做.并没有.这就是你不应该使用DoEvents()的原因.你应该使用线程.即使他们为你提供了一套完整的方法,以丰富多彩,不可思议的方式射击你的脚.但是你的优点是你只能射击自己的脚; 它不会(通常)让用户拍摄她的照片.
下一版本的C#和VB.NET将使用新的await和async关键字提供不同的枪支.所造成的的DoEvents和线程,但通过WinRT中的API设计大的一部分,麻烦少部分的启发,需要你保持你的UI更新,而异步操作正在发生.喜欢从文件中读取.
RQD*_*QDQ 29
它可以,但它是一个黑客.
调用此方法会导致在处理所有等待窗口消息时挂起当前线程.如果消息导致触发事件,则可以执行应用程序代码的其他区域.这可能会导致您的应用程序出现难以调试的意外行为.如果执行需要很长时间的操作或计算,通常最好在新线程上执行这些操作.有关异步编程的更多信息,请参阅异步编程概述.
所以微软警告不要使用它.
此外,我认为它是一个黑客,因为它的行为是不可预测的和副作用倾向(这来自尝试使用DoEvents而不是启动新线程或使用后台工作程序的经验).
这里没有大男子主义 - 如果它作为一个强大的解决方案,我会全力以赴.但是,尝试在.NET中使用DoEvents只会给我带来痛苦.
Bil*_*l W 23
是的,System.Windows.Forms命名空间中的Application类中有一个静态DoEvents方法.在UI线程中执行长时间运行的任务时,System.Windows.Forms.Application.DoEvents()可用于处理UI线程上队列中等待的消息.这样做的好处是,在长任务运行时,UI看起来更具响应性并且不会"锁定".但是,这几乎总是不是最好的做事方式.根据微软调用DoEvents"...导致当前线程被暂停,同时处理所有等待窗口消息." 如果触发事件,则可能会出现难以追踪的意外和间歇性错误.如果你有一个广泛的任务,最好在一个单独的线程中完成它.在单独的线程中运行长任务允许在不干扰UI继续平稳运行的情况下处理它们.看这里了解更多详情.
以下是如何使用DoEvents的示例; 请注意,Microsoft也提供了使用它的警告.
Cra*_*ton 13
根据我的经验,我建议在.NET中使用DoEvents时要非常谨慎.在包含DataGridViews的TabControl中使用DoEvents时,我遇到了一些非常奇怪的结果.另一方面,如果你所处理的只是一个带有进度条的小表格,那么它可能没问题.
底线是:如果您要使用DoEvents,则需要在部署应用程序之前对其进行彻底测试.
Fre*_*els 11
是.
但是,如果您需要使用Application.DoEvents,这主要表明应用程序设计不良.也许你想在一个单独的线程中做一些工作呢?
小智 5
我在上面看到了 jheriko 的评论,并且最初同意如果您最终旋转主 UI 线程等待另一个线程上长时间运行的异步代码完成,我无法找到避免使用 DoEvents 的方法。但是从 Matthias 的回答来看,我的 UI 上一个小面板的简单刷新可以替换 DoEvents(并避免令人讨厌的副作用)。
关于我的案例的更多细节......
我在做以下操作(建议在这里),以确保进度条型闪屏(如何显示“加载”覆盖...)长时间运行的SQL命令时更新:
IAsyncResult asyncResult = sqlCmd.BeginExecuteNonQuery();
while (!asyncResult.IsCompleted) //UI thread needs to Wait for Async SQL command to return
{
System.Threading.Thread.Sleep(10);
Application.DoEvents(); //to make the UI responsive
}
Run Code Online (Sandbox Code Playgroud)
坏处:对我来说,调用 DoEvents 意味着鼠标点击有时会在我的启动画面后面的表单上触发,即使我将它设为 TopMost。
好的/答案:用一个简单的 Refresh 调用替换 DoEvents 行,调用我的启动屏幕中心的一个小面板FormSplash.Panel1.Refresh()。UI 更新得很好,其他人警告的 DoEvents 怪异现象消失了。
| 归档时间: |
|
| 查看次数: |
170148 次 |
| 最近记录: |