Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
6年前关闭。
Improve this question
我是Delphi的noobie,所以对任何愚蠢的问题感到抱歉。
我的主管向我解释说Application.ProcessMessages可以防止应用程序冻结并分配一些额外的计算时间。但是在此命令的文档中,总是有关于已处理的队列系统的某些说明?
请有人能解释一下我的情况吗?
在程序的较大结构中,主线程中的执行如下所示:
检查消息 对于每个消息-执行相关的处理程序 返回到“检查消息(循环)”
因此,当相关处理程序之一(上面的
当然,您已经经历过-突然,您的应用程序无法响应点击。您无法与之交互,也无法移动该窗口,如果在其顶部拖动另一个窗口,该应用程序甚至不会重新绘制自身-它只会填满留在其上的所有垃圾。
输入ProcessMessages
不将长时间运行的代码放入线程的懒惰,可怕的解决方案
当您调用
从表面上看,这似乎是明智的选择,因为它使您可以在长时间运行的循环中保持应用程序的响应速度。然而,最终,由于许多非常好的原因,这种编程风格被广泛认为是极差的实践。可以说,在任何想使用
有关更多详细信息,让我们看一下实际代码:
因此,当您对
最重要的一点是,使用程序时所经历的流畅,流畅的交互是一种完全的错觉,而这完全取决于尽快处理此消息循环。将消息发布到您的应用程序与处理该消息之间的时间延迟越短,您的应用程序将感觉越活跃并能够响应。
因此,附加到用户界面处理程序的所有代码都应快速运行。长时间运行的操作要么需要中断,以便消息处理可以继续(即:
有关该主题的非常好的文章,请参见:
Peter Under的 A Key's Odyssey
(Internet Archive link ...如果上述死亡)
摘要:本文遵循通过VCL发送按键消息的路径。您将学习如何执行密钥处理,OnKey事件如何工作以及在整个过程中可以找到程序员的哪些干预点。此外,还说明了诸如消息处理之类的内容,您将学习如何在调试器中从消息循环到其最终目标跟踪消息。
想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
6年前关闭。
Improve this question
我是Delphi的noobie,所以对任何愚蠢的问题感到抱歉。
我的主管向我解释说Application.ProcessMessages可以防止应用程序冻结并分配一些额外的计算时间。但是在此命令的文档中,总是有关于已处理的队列系统的某些说明?
请有人能解释一下我的情况吗?
最佳答案
没有捷径可以正确回答这个问题。
Windows应用程序与操作系统交互的主要方式是通过消息传递系统。 Windows应用程序中发生的所有事情都是响应消息而发生的。
例如:
如果您在屏幕上单击,则操作系统将决定单击哪个应用程序,然后向该应用程序发布一条消息,指示该应用程序已收到单击(以及该单击的位置)。
如果移动了窗口并在其下面显示了应用程序的一部分,则操作系统会发送一条消息,告诉您的应用程序重新绘制自身。
list 继续。发生的一切都是由消息驱动的。
现在,每个应用程序都有一个主要的用户界面线程(“Main”线程),并且该线程具有一个主要功能-它在无限循环中运行,该循环检查来自操作系统的这些消息,然后执行必要的代码以响应这些消息。
问题
您随即开始编写应用程序。您可能会编写如下代码:
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
时,您正在做的事情是,在这些处理程序之一的中间,指示主线程休息一下以返回检查消息队列并清空所有已堆积的消息。处理任何单击,窗口移动,输入,击键,并在需要时重绘(repaint)自身,等等。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
),要么这些操作需要移到一个单独的线程中,在其中他们可以执行而无需占用主线程并使它脱离主要职责(是为了使用户界面保持 Activity 状态)。有关该主题的非常好的文章,请参见:
Peter Under的 A Key's Odyssey
(Internet Archive link ...如果上述死亡)
摘要:本文遵循通过VCL发送按键消息的路径。您将学习如何执行密钥处理,OnKey事件如何工作以及在整个过程中可以找到程序员的哪些干预点。此外,还说明了诸如消息处理之类的内容,您将学习如何在调试器中从消息循环到其最终目标跟踪消息。
关于delphi - 我不明白Delphi中的Application.ProcessMessages在做什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25181713/
10-08 22:41