Molochnik
Molochnik

Reputation: 742

Delphi Application Run

The Application.Run procedure calls an infinite loop that handles windows messages:

  repeat
    try
      HandleMessage;
    except
      HandleException(Self);
    end;
  until Terminated;

The Terminated property can be set to true only through Application.Terminate procedure, which sends PostQuitMesage. I would like to change the message handling loop so that I can directly stop it using the global variable (without using messages queue):

var MyTerminated:Boolean
....
  repeat
    try
      HandleMessage;
    except
      HandleException(Self);
    end;
  until Terminated or MyTerminated;

The question is, is it possible to make the program use your own version of Application.Run?

Upvotes: 2

Views: 2103

Answers (2)

Maxim Masiutin
Maxim Masiutin

Reputation: 4782

Yes, you can make your application use your own version of Application run, but this practice is discouraged because it changes the normal program flow designed by architects of Delphi.

Directly stopping the Application.Run signifies that there is a need to restart Application.Run later, for example, after some action that is wanted to be performed from the main thread. This makes the program puzzled, harder to understand by peer programmers and is more error prone as a whole.

The program design should be simple and straightforward. If an application is big, for example containing two million lines of code, the overall design of the execution flow should be simple anyway:

  • If you need to do some longer actions do them from the worker threads;
  • If you need to do an instant actions do them from your main form or from the other forms.

So a Delphi application's main loop should only be exited on the overall application exit, which is done by the PostQuitMessage. We don't have to avoid this message.

The reason when the PostQuitMessage is wanted to be avoided is probably an instantaneous exit. This is not how VCL applications are supposed to run. If one doesn't need any forms (for example for a Windows Service application), just don't use the TApplication class and don't run forms, just make your own message loop based on MsgWaitForMultipleObjects.

Upvotes: 1

Sertac Akyuz
Sertac Akyuz

Reputation: 54802

"Terminated" property is read-only. However it is a direct getter of the FTerminated field, therefore Application.Terminated directly reads from the boolean field. While the language disallows setting Application.Terminated, you can set the boolean value at that address using a pointer:

PBoolean(@Application.Terminated)^ := True;

You may also consider using Halt, which will pass over the message loop completely, for a more abrupt but less hacky solution.

Upvotes: 6

Related Questions