Setze ich auf CT.Free einen Breakpoint und steppe rein, geht es zu TCustomThread.Destroy.
Als nächstest wird TCustomThread.TerminatedSet angesprungen und dort ist FIsOpen = False!
Was ja richtig ist, denn laut System.Classes und Log-Ausgabe wird TerminatedSet doch schon vorher
durch Terminate aufgerufen. Warum also der erneute Aufruf von Destroy?
Eventuell weil das so programmiert wurde?
Oh, ja ein Blick in den Source und schon weiß man mehr
Delphi-Quellcode:
destructor TThread.Destroy;
begin
if (FThreadID <> 0) and not FFinished and not FExternalThread then
begin
Terminate;
if FCreateSuspended or FSuspended then
Resume;
{$IFDEF MSWINDOWS}
while not FStarted do
{$ELSE}
while not ((not FCreateSuspended or FInitialSuspendDone) and FStarted) do
{$ENDIF}
Yield;
WaitFor;
end;
RemoveQueuedEvents(Self);
{$IF Defined(MSWINDOWS)}
if (FHandle <> 0) and not FExternalThread then CloseHandle(FHandle);
{$ELSEIF Defined(POSIX)}
// This final check is to ensure that even if the thread was never waited on
// its resources will be freed.
if (FThreadID <> 0) and not FExternalThread then pthread_detach(pthread_t(FThreadID));
pthread_mutex_destroy(FCreateSuspendedMutex);
{$ENDIF POSIX}
inherited Destroy;
FFatalException.Free;
end;
Es stellt sich natürlich die Frage, warum du in
TerminatedSet
den Stream freigibst.
Das ist ungefähr so, als wenn du bei einem
fahrenden Auto einfach mal die Zündkerzen ausbaust, weil du willst das Auto ja eh anhalten.
Lass das Auto (den Thread) doch erst mal zum Stehen kommen.