Application.DoEvents()以让UI线程在当前代码上下文中切换去处理其它Windows消息,从而避免界面的假死。
如在一个按钮单击事件中,需要每一秒改变label的Text属性,如下代码:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 50; i++)
{
Thread.Sleep(500);
this.label1.Text = i.ToString();
}
}
编译运行,单击按钮,你并不会见到lable一直改变,等到执行完,你只会看见49。而加上 Application.DoEvents() 方法则可以看到一直更改的文本
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 50; i++)
{
Thread.Sleep(500);
this.label1.Text = i.ToString();
Application.DoEvents();
}
}
勇哥在下面的WaitMotorDone函数中,原本使用的DoEvnets(),
本意是当用于ui调用时,可以在运动中能不卡住界面(有机会更新界面信息)。
你从函数名可以知道,此函数由运动函数调用,它等待轴停止,然后退出。
我的一个ptp运动函数调用了WaitMotorDone。
界面上一个按钮调用了这个ptp运动函数,当逻辑中有多条连续的ptp运动函数时,执行就异常了。
表现为第二个或者第三个ptp运动函数无效退了,即运动函数执行了轴没动作,但是函数执行完成了。
如果把WaitMotorDone中的Applictation.DoEvnets()注释了,问题就解决了。
当然,如果你用一个线程去调用运动函数,即使没有注释掉DoEvents(),也是没有问题的。
这说明Application.DoEvents()和ui线程有某些冲突。
毕竟只有winform才有消息循环,而Applictation.DoEvnets()就是处理消息循环的功能。
那么使用下面的代码,可以解决问题吗。
if (Application.MessageLoop) Application.DoEvents();
这个代码的意思,勇哥参考微软的说明,指的是: 如果当前线程存在消息循环的值,则执行Applictation.DoEvnets()。
即如果是ui线程调用下这个if会命中,如果在其它线程下调用这个if会命中不了。
因此,加这个if也解决不了上面说的异常。
由网上找到的资料,表明Applictation.DoEvnets()实际上是VB时代的旧物,除了兼容考虑,其它情况下不要使用。
原文摘抄如下:
DoEvents 是 vb(4、5、6)的产物,因为那是单线程的。
它的机制是将你的应用中尚未触发的windows消息大乱次序、提前触发。
比如说你在鼠标点击某个控件时会去调用过程a,在鼠标在此控件移动时会去调用过程b,
同时在timer定时器到时时回去调用过程c,
那么你会看到DoEvents 造成了在a尚未结束时反复调用了b、c等等过程,
主线程中明明是顺序的代码,调用时一片混乱无法调试。
而且往往会导致事件的爆炸性的循环调用(类似于无线递归没有节制),直至系统资源耗尽而崩溃。
正常的主线程异步操作,是可以明确地知道过程在主线程中被调用的先后次序的,
可以明白地调试代码(明白地看懂调用堆栈)。
主线程都是先调用完a,然后才可能调用b、c,并不是在过程中去拆自己的台。
因此如果需要循环触发,那么就使用定时器。
DoEvents是vb那个时代的产物,应该终止与vb6(1998年)的时代。
如果你要简单移植vb6的程序,可以用它。如果不是就不要用它。
另外,在应用程序设计中搞“死循环”这是很令人不忍看、不忍“闻”的设计方式。
如果你认为主线程经常要重复干一件(逻辑的)事儿,就必须写一个死循环,
那么我只能说我们是绝对不用这样的程序员的。
在设计上,除非万不得已实在活不下去了,否则不允许随便写“死循环、阻塞”的代码。
写死循环,是因为有些人只知道刚入门学c等等几十行的简单小计算程序时学到的那种思路,
因为那些是“输入-输出”式的简单函数。
如果你学习交互式程序设计,假设有10个独立的(貌似循环)的功能行为,那么凡是交互部分,
都必须“断开”,然后每一个片段都必须是事件驱动(包括定时器事件驱动),
这样才能组合成为一个完善的应用。
难道你要写10个死循环,然后再胡乱地DoEvents调用?这是编程大忌。
把设计中各种事件循环发生,代码上写成许多个死循环,这是没有学过应用程序设计的表现
(可能只是从一些数学相关的课程中学了一些简单的函数编程)。
一定要从设计思路上学会事件驱动的设计方法,而不是纠结于编程语句。
所以, 各位同学们还是快快检查下自己的代码,放弃Applictation.DoEvnets()吧!
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

