I do not understand what Application.ProcessMessages in Delphi is doing [closed]

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

(Internet Archive link… in case the above dies)

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.

Leave a Comment