avatar

Andres Jaimes

Tips to help you deal with Delphi Threads

By Andres Jaimes

Multithreading is one of those operating systems feaures that make your programs work in a more efficient way and give your users a better interactive interface. However they are not used by all developers.

In this article I will focus on some important points you must have in mind when using threads on Delphi.

 

How to create them

There are two simple steps to accomplish it:

  1. Create a new class that inherits from TThread and
  2. Override the Execute method.
TMyThread = class(TThread)
public
  procedure Execute; override;
end;

procedure TMyThread.Execute;
begin
   DoSomeWork();
  //When the procedure ends, the thread ends.
end;

 

How to call them

The default constructor accepts a parameter that instructs the new thread to start immediatly after construction or remain suspended. Remember you can override constructors, but make sure you call inherited inside it in order to execute the parent class constructor too.

The following snippet will create a thread everytime StartButton is clicked.

procedure TForm.StartButtonClick(Sender: TObject);
begin
  TMyThread.Create(false);
end;

 

FreeOnTerminate

FreeOnTerminate is an important property. When it is true, it will free all related resources when the thread execution finishes.

If you need to access some of your thread’s resources after finalization, like property values, set this property to false. In this case remember to call your thread’s free procedure.

 

Priority

You can change your thread priority by changing the Priority property to any of the following values: tpIdle, tpLowest, tpNormal, tpHigher, tpHighest, tpTimeCritical.

 

User Interface Synchronization

UI synchronization must be done through calls to Synchronize. This procedure sends a message to the main thread’s message queue instructing it to execute the given procedure. When the main queue finds this message, it will pause the calling thread until the code finishes executing.

Synchronize uses Windows’ SendMessage API function to put the message in the main thread’s queue. Synchronize is a thread safe procedure and you should use it to make any UI update.

procedure TMyThread.Execute;
begin
   while something do begin
     DoSomeWork();
     Synchronize(UpdateUI);
  end
end;

procedure TForm.UpdateUI;
begin
  // Update the UI like progress bars, etc.
end;

 

Using Global Variables and VCL components

Yes, you have access to global variables (usually from your main form) to accomplish UI update. When calling Synchronize, you send two parameters:

  1. The calling thread and
  2. The procedure to be called by the main thread

Since the procedure to be called (the second one in the previous list) is executed by the main thread, then you can have access to all variables and VCL components used in your form.

 

Asynchronous Calls

To perform asynchronous calls you have to use the Queue procedure, which uses the Windows’ PostMessage API function.