This is a basic design flaw with the Delphi 5 implementation of TThread
. The underlying Windows thread is started in the constructor of TThread
. Which leads to the race that you describe.
In the Delphi 6 version of the RTL, the thread start mechanism was changed. From Delphi 6 onwards, the thread is started in TThread.AfterConstruction
. And that runs after the constructor completes. That would render your code race free.
In Delphi 6 and later, the underlying Windows thread is created in the TThread
constructor, but is created suspended using the CREATE_SUSPENDED
flag. Then in AfterConstruction
, so long as TThread.FCreateSuspended
is False
, the thread is resumed.
One way to work around the issue in Delphi 5 is to call the inherited constructor last. Like this:
constructor TJvHidDeviceReadThread.CtlCreate(const Dev: TJvHidDevice);
begin
Device := Dev;
NumBytesRead := 0;
SetLength(Report, Dev.Caps.InputReportByteLength);
inherited Create(False);
end;
Rather ugly I know.
So, your approach of creating the thread suspended and resuming once the constructor has completed is probably better. That approach mirrors how the RTL solves the problem in Delphi 6 and up.