我不明白Delphi中的Application.ProcessMessages在做什么 [英] I do not understand what Application.ProcessMessages in Delphi is doing

查看:128
本文介绍了我不明白Delphi中的Application.ProcessMessages在做什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的主管向我解释说Application.ProcessMessages可以防止冻结应用程序并分配一些额外的数据计算时间。但是在这个命令的文档中总是解释一下处理的队列系统?
请有人向我解释上下文?

解决方案

正确回答这个问题没有什么简短的方法。



Windows应用程序与操作系统交互的主要手段是通过消息传递系统。在Windows应用程序中发生的一切都发生在响应消息中。



例如:



如果您点击屏幕,操作系统决定哪个应用程序被点击,并向该应用程序发布一条消息,指示它已经收到点击(以及该点击的位置)。



如果窗口被移动并显示在其下的应用程序的一部分,操作系统会发送一条消息,告诉您的应用程序重新绘制自己。



列表继续。发生的一切都是由消息驱动的。



现在,每个应用程序都有一个主要的用户界面线程(Main线程)),这个线程有一个主要功能 - 运行在一个无限循环中,从操作系统检查这些消息,然后执行必要的代码以响应这些消息。



问题



你来了,开始写一个应用程序。你可以编写一些这样的代码:

  procedure TForm1.Button1Click(Sender:TObject); 
var i:整数;
begin
for i:= 0 to 99999999999 do begin
SolveTheProblemsOfTheWorld(i);
CalculatePiToABillionPlaces;
结束
结束

在程序的较大结构中,主线程中的执行如下所示:


  1. 检查邮件

  2. 对于每个邮件 - 执行相关处理程序

  3. 返回检查邮件(循环)

所以这个循环是快乐的,当突然一个相关的处理程序( Button1Click 以上)开始花费很长时间才能完成。要理解的是,一个消息处理程序必须在下一个消息处理程序运行之前完成。如果您单击滚动条,然后拖动它,但是您将一个处理程序附加到 OnClick 的滚动条需要10秒才能完成,那么在该点击处理程序完成之前,您的应用程序将不会看到拖动操作。在此期间,消息队列正在填补,主线程没有做任何事情。



您当时遇到过这种情况 - 突然您的应用程式无法响应点击。你不能与它交互,你不能移动窗口,如果你拖动另一个窗口在它的顶部,应用程序甚至不会重绘自己 - 它只是填满了你留下的任何垃圾。 p>

输入ProcessMessages



懒惰,可怕的解决方案, - 将代码转换为线程



当您调用 Application.ProcessMessages 时,您正在做什么在这些处理程序之一的中间,指示主线程休息一下,检查消息队列并清空堆栈中的任何消息;处理任何点击,窗口移动,输入,击键,如果需要,重新绘制自己等。

 程序TForm1.Button1Click(发件人:TObject) 
var i:整数;
begin
for i:= 0 to 99999999999 do begin
SolveTheProblemsOfTheWorld(i);
CalculatePiToABillionPlaces;
Application.ProcessMessages;
结束
结束

这可能看起来像一个明智的做法,因为它可以让您在长跑循环。然而,最终,这种编程风格被广泛认为是非常糟糕的做法,因为很多很好的理由。只要说在任何你试图使用 Application.ProcessMessages 的任何地方,将这个工作转移到后台线程就是一个很好的例子。



有关更多详细信息,请查看实际代码:

  procedure TApplication.ProcessMessages; 
var
Msg:TMsg;
begin
,而ProcessMessage(Msg)do {loop};
结束

所以当你打电话给 Application.ProcessMessages 您正在运行一个循环,一个一个地从消息队列中清空消息(并且执行所有与这些消息反应的处理程序相关的代码),直到它为空。当它是空的并且没有更多的消息要处理时,控制将返回到程序中的下一行。



要解决的重点是,使用程序时遇到的平滑互动是一个完全错觉,完全依赖于尽快处理的消息循环。发送到您的应用程序的消息和正在处理的消息之间的时间延迟越小,您的应用程序将会感觉到它的存活和响应越多。



正是由于这个原因,附加到用户界面处理程序的所有代码应该快速运行。长时间运行的操作需要中断,以便消息处理可以继续(即: Application.ProcessMessages )或者这些操作需要移动到一个单独的线程,在那里它们可以执行没有捆绑主线,脱离主要责任(即保持用户界面活跃)。






有关该主题的一篇很好的文章,请参阅:



A Key's Odyssey 由Peter Under



Google缓存链接 ...服务器似乎忙于我)



摘要:本文遵循通过VCL的按键消息的路径。您将了解如何实现关键处理,OnKey事件的工作原理以及在整个过程中可以找到程序员的干预措施。此外,还将解释消息处理等问题,您将学习如何从调试器中跟踪消息循环中的消息到最终目的地。


I'm a noobie in Delphi, so sorry for any silly question.

My supervisor explained me that Application.ProcessMessages prevents freezing of the application and allocates some extra computing time. But in the docs of this command is always something explained about a queue system which is processed? Please can somebody explain me the context?

解决方案

There is no short way to answer this question properly.

The primary means by which Windows applications interact with the operating system is via a messaging system. Everything that happens in a windows application happens in response to a message.

For example :

If you click on the screen, the operating system decides which application got clicked and posts a message to that application indicating that it has received a click (along with the location of that click).

If a window is moved and reveals a part of your application beneath it, the operating system sends a message telling your application to repaint itself.

The list goes on. Everything that happens is driven by messages.

Now, each application has one primary user-interface thread (the "Main" thread) and this thread has one primary function - it runs in an infinite loop that checks for these messages from the operating system and then executes the necessary code in response to those messages.

The Problem

You come along and start writing an application. You might write some code like this :

procedure TForm1.Button1Click(Sender: TObject);
var i : Integer;
begin
  for i := 0 to 99999999999 do begin
    SolveTheProblemsOfTheWorld(i);
    CalculatePiToABillionPlaces;
  end;
end;

In the larger structure of the program, execution in the main thread looks like this:

  1. Check for messages
  2. For each message - execute the associated handlers
  3. Go back to Check for messages (loop)

So this loop is happily wizzing along when suddenly one of the associated handlers (Button1Click above) starts taking a very long time to complete. Key to understand is that one message handler must complete before the next one can run. If you click a scrollbar, for example, and drag it, but you've attached a handler to OnClick of the scrollbar that takes 10s to complete, then the drag operation will not be seen by your application until that click handler completes. In the meantime, the message queue is filling up and the main thread is not doing anything about it.

Surely you've experienced this - suddenly your application does not respond to clicks. You can't interact with it, you can't move the window, if you drag another window around overtop of it the application won't even repaint itself - it just fills up with whatever garbage you left on top of it.

Enter ProcessMessages

The lazy, terrible solution to not putting your long-running code into a thread

What you are doing when you are calling Application.ProcessMessages is, in the middle of one of these handlers, instructing the main thread to take a break to go back to check the message queue and empty any messages that have been piling up; to handle any clicks, window movements, inputs, keystrokes, to repaint itself if needed, etc.

procedure TForm1.Button1Click(Sender: TObject);
var i : Integer;
begin
  for i := 0 to 99999999999 do begin
    SolveTheProblemsOfTheWorld(i);
    CalculatePiToABillionPlaces;
    Application.ProcessMessages;
  end;
end;

This may seem superficially like a sensible thing to do since it allows you to keep the application responsive during a long-running loop. Ultimately, however, this style of programming is widely considered to be extremely poor practice for a large number of very good reasons. Suffice it to say that anywhere you are tempted to use Application.ProcessMessages is a solid case for moving that work to a background thread instead.

For more detail, let's have a look at the actual code :

procedure TApplication.ProcessMessages;
var
  Msg: TMsg;
begin
  while ProcessMessage(Msg) do {loop};
end;

So when you make this call to Application.ProcessMessages you are running a loop that is, one by one, emptying messages from the message queue (and executing all of the code that is attached to handlers that are reacting to those messages) until it is empty. When it is empty and there are no more messages to process, control will return to the next line in your program.

The important point to take away is that the fluid, smooth interaction you experience when using a program is a complete illusion that depends exactly on this message loop being processed as quickly as possible. The smaller the time delay between a message being posted to your application and the message being handled, the more your application will feel like it is alive and responsive.

It is for this reason that all code that is attached to user-interface handlers should be fast running. Long running operations either need to be interrupted so that message handling can continue (ie: Application.ProcessMessages) or those operations need to be moved to a separate thread where they can execute without tying up the main thread and taking it away from its primary responsibility (which is to keep the user-interface alive).


For a really good article on the topic, see :

A Key's Odyssey by Peter Below

(Google cache link... server seems busy for me)

Abstract: This article follows the path of a keystroke message through the VCL. You will learn how the key processing is implemented, how the OnKey events work and what intervention points for the programmer can be found in the whole process. In addition, things like message processing are explained, and you will learn how to trace messages in the debugger from the message loop to their eventual destination.

这篇关于我不明白Delphi中的Application.ProcessMessages在做什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆