Threadvar Keyword
The threadvar
keyword starts a variable
declaration in the same manner as the var
keyword,
except that threadvar
can be used only at the unit
level. Variables declared using threadvar
have
distinct values in each thread. Ordinary variables, on the other
hand, are shared among all threads in a
process.
If you are using the TThread
class
(Classes
unit), you will probably find it more
convenient to use fields to store per-thread data.
If you are writing a reusable subroutine or class that might be used
in multiple threads, you can use threadvar
variables to keep track of per-thread information.
Threadvar
declarations apply only to the variable
itself. If the variable is a pointer or encapsulates a pointer (e.g.,
object, long string, dynamic array, Variant
), the
data might be accessible from multiple threads.
Threadvar
variables use Windows thread-local
storage (TLS). Every variable access requires a function call, so
another reason to use the TThread
class is that
access to the object’s fields is faster than using
threadvar
variables.
Every module that uses a threadvar
variable
requires a TLS slot, but Windows has a small number of TLS slots
available. A large project should use packages to ensure the
availability of this limited resource.
Every module (application, DLL, package) that contains a
threadvar
variable needs its own, separate TLS
slot. If you link a DLL statically, the DLL contains its own copy of
the System
unit and its
IOResult
and RaiseList
variables (which are threadvar
variables). A
project with a large number of DLLs can run out of TLS slots even if
they don’t have their own threadvar
variables.
If you use packages, the vcl50 package contains
the shared instance of the System
unit and its
threadvar
variables. That means the project needs
only one TLS slot, no matter how many DLLs and packages it loads. If
any DLL or package needs its own threadvar
variables, only that module would need another TLS slot.
Do not use threadvar
variables in the finalization
section of a unit that might be used in a DLL. Delphi frees the TLS
memory when it unloads the DLL, but before it calls the finalization
sections.
// Each thread has a separate List variable, but it is up to the
// programmer to assign a unique TList object to each List variable.
threadvar
List: TList;
procedure ThreadFunc(Param: Pointer);
begin
List := TList.Create;
...
end;
procedure StartThread;
begin
Handle := BeginThread(nil, 0, ThreadFunc, nil, 0, Id);
end;