Using the Main VCL Thread

From RAD Studio
Jump to: navigation, search

Go Up to How To Build Multithreaded Applications

Using the main VCL thread consists of the following basic steps:

  1. Create a separate routine to handle Windows messages received by components in your application.
  2. Call CheckSynchronize periodically.
  3. Declare thread-local variables, as necessary, for exclusive use by your thread.

To create a separate routine

  1. Write a main thread routine that handles accessing object properties and executing object methods for all objects in your application.
  2. Call the routine using the TThread.Synchronize. The following code is an example of how to call a method using Synchronize:
procedure TMyThread.PushTheButton
begin
  Button1.Click;
end;
procedure TMyThread.Execute;
begin
  // ...
  Synchronize(PushThebutton);
  // ...
end;
void __fastcall TMyThread::PushTheButton(void) {
    Button1->Click();
}

// ...

void __fastcall TMyThread::Execute() {
    Synchronize((TThreadMethod)PushTheButton);
}

Synchronize waits for the main thread to enter the message loop and then executes the passed method.

Note: Because Synchronize uses a message loop, it does not work in console applications. For console applications, use other mechanisms, such as critical sections, to protect access to VCL objects.

To call CheckSynchronize

  1. Call CheckSynchronize periodically within the main thread to enable background threads to synchronize execution with the main thread.
  2. To ensure the safety of making background thread calls, call CheckSynchronize when the application is idle, for example, from an OnIdle event handler.

To use a thread-local variable

Identify variables that you want to make global to all the routines running in your thread but not shared by other instances of the same thread class.

For Delphi, declare these variables in a threadvar section, for example:

threadvar
  x: integer;
Note: Use the threadvar section for global variables only. Do not use it for Pointer and Function variables or types that use copy-on-write semantics, such as long strings.

In C++Builder, make a variable thread-local by adding the __thread modifier to the variable declaration. For example,

int __thread x;

declares an integer type variable that is private to each thread in the application, but global within each thread.

The __thread modifier can only be used for global (file-scope) and static variables. Pointer and Function variables can't be thread variables. Types that use copy-on-write semantics, such as AnsiStrings don't work as thread variables either. A program element that requires runtime initialization or runtime finalization cannot be declared to be a __thread type.

The following declarations require runtime initialization and are therefore illegal.

    int f();
    int __thread x = f(); // illegal

Instantiation of a class with a user-defined constructor or destructor requires runtime initialization and is therefore illegal:

class X {
	X();
	~X();
};

X __thread myclass; // illegal

See Also