我的主管向我解释说Application.ProcessMessages防止冻结应用程序并分配一些额外的计算时间。但是在这个命令的文档中总是解释一下处理的队列系统?
请问有人可以解释我的上下文吗?
解决方法
Windows应用程序与操作系统交互的主要手段是通过消息系统。在Windows应用程序中发生的一切都发生在响应消息中。
例如 :
如果您点击屏幕,操作系统将决定哪个应用程序被点击,并向该应用程序发布一条消息,指示它已经收到点击(以及该点击的位置)。
如果一个窗口被移动并显示在其下面的一部分应用程序,则操作系统会发送一条消息,告诉您的应用程序重新绘制本身。
列表继续。发生的一切都是由消息驱动的。
现在,每个应用程序都有一个主要的用户界面线程(“主”线程),而这个线程有一个主要功能 – 它运行在一个无限循环中,从操作系统检查这些消息,然后执行必要的代码以响应那些消息。
问题
你来吧,开始写一个应用程序。你可以编写一些这样的代码:
procedure TForm1.Button1Click(Sender: TObject); var i : Integer; begin for i := 0 to 99999999999 do begin SolveTheProblemsOfTheWorld(i); CalculatePiToABillionPlaces; end; end;
在程序的较大结构中,主线程中的执行如下所示:
>检查邮件
>对于每个消息 – 执行相关的处理程序
>返回检查邮件(循环)
所以这个循环是高兴的,当突然之间的相关处理程序(上面的Button1Click)开始需要很长时间才能完成。要了解的一点是,一个消息处理程序必须在下一个消息处理程序运行之前完成。例如,如果您单击滚动条并拖动它,但是您已经将一个处理程序附加到滚动条的OnClick上,需要10秒才能完成,那么在该点击处理程序完成之前,您的应用程序将不会看到拖动操作。在此期间,消息队列正在填补,主线程没有做任何事情。
当然你经历过这个 – 突然你的应用程序没有响应点击。你不能与它进行交互,你不能移动窗口,如果你拖动另一个窗口在它的顶部,应用程序甚至不会重绘自己 – 它只是填满了你留下的任何垃圾。
输入ProcessMessages
当您调用Application.ProcessMessages时,您正在执行的操作是在其中一个处理程序的中间,指示主线程休息一下,以检查消息队列并清空堆栈中的任何消息;处理任何点击,窗口移动,输入,击键,如果需要,重新绘制自己等。
procedure TForm1.Button1Click(Sender: TObject); var i : Integer; begin for i := 0 to 99999999999 do begin SolveTheProblemsOfTheWorld(i); CalculatePiToABillionPlaces; Application.ProcessMessages; end; end;
这可能看起来像一个明智的做法,因为它允许您在长时间运行的循环中保持应用程序的响应。然而,最终,这种编程风格被广泛认为是非常糟糕的做法,因为很多很好的理由。只要说,任何你试图使用Application.ProcessMessages的事情都是把这个工作移到后台线程的一个实例。
有关更多详细信息,请查看实际代码:
procedure TApplication.ProcessMessages; var Msg: TMsg; begin while ProcessMessage(Msg) do {loop}; end;
因此,当您对Application.ProcessMessages进行此调用时,您将逐个运行一个循环,从消息队列中清空消息(并执行附加到对这些消息做出响应的处理程序的所有代码),直到它空。当它为空并且没有更多消息要处理时,控件将返回到程序中的下一行。
要解决的重要问题是,使用程序时遇到的流畅,平滑的交互是完全错误的,这完全依赖于尽可能快地处理的消息循环。发送到您的应用程序的消息和正在处理的消息之间的时间延迟越小,您的应用程序将会感觉到它的存活和响应越多。
正是由于这个原因,附加到用户界面处理程序的所有代码应该快速运行。长时间运行的操作需要中断,以便消息处理可以继续(即:Application.ProcessMessages),或者这些操作需要移动到一个单独的线程,在那里它们可以执行,而不需要绑定主线程并将其从主要责任中移除(这是为了保持用户界面活着)。
彼得下面的A Key’s Odyssey
(Google cache link …服务器似乎忙于我)
摘要:本文介绍了通过VCL进行按键消息的路径。您将了解如何实现关键处理,OnKey事件的工作原理以及在整个过程中可以找到程序员的干预措施。另外,解释消息处理的内容,您将学习如何在调试器中跟踪消息循环中的消息到最终目的地。