Application.DoEvents()

11/25/2015来源:ASP.NET技巧人气:3980

今天,在按照书上的一个winform例子做练习(实则就是边看边抄了一遍...)的时候,看到application.DoEvents()这个方法,但是并不明白这个方法是做什么用的。只知道不用这个方法的话,在循环做耗时操作的时候,窗口ui绘制会出现问题。

于是在网上查找了一下,但是头昏脑涨的,那些理论和概念对我来讲,有点难懂。但是眼前我只是想理解这个方法的作用,于是便按照自己的理解去浅显的给它作出解释。

 PRivate void btnCopy_Click(object sender, EventArgs e)
        {
            List<FileInfo> fileList = GetFileList();
            foreach (FileInfo file in fileList)
            {
                try
                {
                    labStatus.Text = "Copying " + txtTargetDir.Text + "\\" + file.Name + "...";
                    Application.DoEvents();
                    //复制文件到目标位置
                    file.CopyTo(txtTargetDir.Text + "\\" + file.Name, chbOverWrite.Checked);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            labStatus.Text = "Done.";
        }

上面的代码是我做练习时候的其中一段,目的是点击copy按钮的时候,在名为labStatus的label上显示一段文字,然后后台就copy一个文件,如此循环,直到要copy的文件全部copy完成,最后将labStatus上的文字变成Done。

如此运行的话,是没有什么问题的。但是我不太理解Application.DoEvents()方法在这里起了何种作用,于是将Application.DoEvents()注释掉再运行。当我点击copy之后,窗口像是“死掉”了一样,但是后台的文件确实是正在复制,复制完成之后,labStatus的text变成done。

在我查找资料的过程中,我才知道windows的消息机制。但是那些深入的理论,对于我目前来说有点看着头疼,看了也看不懂,又不会去用,看了也会忘记的。于是我浅显的了解了一点目前需要的。

以下看起来比较书面的文字,是我抄录来的。

1,消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。

2,Windows的消息系统是由3个部分组成的:

 

  ·消息队列。Windows能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取消息,然后分派给某个窗口。

 

  ·消息循环。通过这个循环机制应用程序从消息队列中检索消息,再把它分派给适当的窗口,然后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。

 

  ·窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后响应它。窗口过程是一个回调函数;处理了一个消息后,它通常要返回一个值给Windows。

3,一个消息从产生到被一个窗口响应,其中有5个步骤:

  1) 系统中发生了某个事件。

  2) Windows把这个事件翻译为消息,然后把它放到消息队列中。

  3)应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中。

  4)应用程序把消息传递给一个适当的窗口的窗口过程。

  5) 窗口过程响应这个消息并进行处理。

  步骤3和4构成了应用程序的消息循环。消息循环往往是Windows应用程序的核心,因为消息循环使一个应用程序能够响应外部的事件。消息循环的任务就是从消息队列中检索消息,然后把消息传递给适当的窗口。如果消息队列中没有消息,Windows就允许其他应用程序处理它们的消息。

到这里也就差不多了,其他的资料看了也没看,大概能看懂的也记不住,就不提了。那么回到原本的话题上来,Application.DoEvents()方法在这里起了什么作用?

我的比较浅显的理解是,在上面那段代码里,当我们点击copy按钮之后,在循环中,每一次windows都往当前消息队列里添加了两个消息,一个是labStatus的text要改变,另一个是要copy一个文件,然而copy一个文件很明显是比较耗时的操作。在我注释掉Application.DoEvents()这行代码之后,从运行的窗口展现出来的效果来看,很显然,它是先将copy文件的那个消息响应了,然后在所有的copy文件操作都执行完了之后,再去响应了labStatus的text改变操作,但是一次性执行循环里的所有labStatus的text改变操作的话,我们就只能看得见最后的 labStatus.Text = "Done.";所产生的效果了。当然,在copy过程中,我们要去点击窗口,或者拖动窗口,这些操作是要等到copy之后的。

所以,Application.DoEvents()方法所做的事情,正如它的介绍一样——处理当前在消息队列里的所有windows消息。

但是我还是有很多很多不明白的地方,比如为什么是先响应了copy操作呢?这个队列是怎么排列的呀?不过现在暂且就这样了。以上就是我的个人的理解,它或许根本就是错误的,或许有许多很幼稚的地方,请看到的朋友们告诉我,帮助我的学习,也顺便巩固下您自己。谢谢!