Tra la creazione e l'avvio dell'istanza TThread
, il thread principale continuerà con l'esecuzione del codice. Se il codice nel thread principale dipende dal thread in questione per essere completamente attivo e in esecuzione, esso deve attendere in qualche modo fino a quando il metodo del thread Execute
non viene effettivamente avviato.Qual è il modo corretto di attendere l'avvio dell'istanza TThread
Considerate seguente codice:
const
WM_MY_ACTION = WM_APP + 10;
type
TWndThread = class(TThread)
protected
fWndHandle: THandle;
IsRunning: boolean;
procedure WndProc(var Msg: TMessage);
procedure Execute; override;
public
Test: integer;
procedure AfterConstruction; override;
procedure DoAction;
end;
procedure TWndThread.AfterConstruction;
begin
inherited;
while not IsRunning do Sleep(100); // wait for thread start up
end;
procedure TWndThread.Execute;
var
Msg: TMsg;
begin
fWndHandle := AllocateHWnd(WndProc);
IsRunning := true;
try
while not Terminated do
begin
if MsgWaitForMultipleObjects(0, nil^, False, 1000, QS_ALLINPUT) = WAIT_OBJECT_0 then
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;
finally
DeallocateHWnd(fWndHandle);
end;
end;
procedure TWndThread.WndProc(var Msg: TMessage);
begin
case Msg.Msg of
WM_MY_ACTION:
begin
inc(Test);
end;
else Msg.Result := DefWindowProc(fWndHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;
end;
procedure TWndThread.DoAction;
begin
PostMessage(fWndHandle, WM_MY_ACTION, 0, 0);
end;
var
t: TWndThread;
begin
t := TWndThread.Create;
t.DoAction;
t.Terminate;
end;
Senza ciclo che attende IsRunning
bandiera, DoAction
non sarà in grado di inviare con successo un messaggio di handle di finestra contenuta perché non sarà ancora essere creato. Fondamentalmente, inc(Test)
all'interno di WndProc
non verrà attivato.
Esiste un modo migliore per attendere l'avvio del thread e completare l'inizializzazione necessaria all'interno del metodo Execute
oppure questa soluzione è buona?
Nota: sono consapevole del fatto che AllocateHWnd
e DeallocateHWnd
non sono thread-safe e non devono essere utilizzati nel codice di produzione come nell'esempio precedente.
Ho curato questione - si trasferisce il codice di attesa a 'AfterConstruction' per rendere classe thread più autosufficiente. Presumo che nulla mi impedisca di usare 'TSimpleEvent' anche in modo contenuto? –
Il luogo perfetto per l'attesa è il metodo 'DoAction' o qualsiasi altro metodo pubblico in cui è necessario assicurarsi che tutto sia in esecuzione –
@Sir Rufo è corretto che è meglio aspettare solo quando è necessario attendere –