Percorrer o caminho inverso do fluxo de execução de uma tarefa que é intercalada por threads requer tempo de habilidade.
O Delphi 2010 trás uma novidade interessante que promete ajudar nessa árdua tarefa, agora é possível nomear as threads.
Observe a imagem abaixo:
No Delphi 2010 foi introduzido o método NameThreadForDebugging na classe TThread e é utilizado tanto para nomear quanto para renomear uma thread específica.
Sua assinatura trás dois parâmetros: AThreadName e AThreadID.
O primeiro é o nome que será dado à thread e o segundo parâmetro é o ID da thread a ser nomeada. No caso do segundo parâmetro ser omitido, ou ser -1, a operação será realizada sob a corrente thread que está rodando.
Outro detalhe é que o nome atribuído é do tipo AnsiString, ou seja, pode ser necessário um typecast explícito.
Vamos ver na prática como o recurso é aplicado.
procedure TMyThread.Execute;
var
lThreadName: AnsiString;
begin
{$IFDEF VER210}
lThreadName := AnsiString(Self.ClassName + '_' + IntToStr(FCount));
NameThreadForDebugging(lThreadName);
{$ENDIF}
while not Terminated do
begin
Sleep(300);
end;
end;
var
lThreadName: AnsiString;
begin
{$IFDEF VER210}
lThreadName := AnsiString(Self.ClassName + '_' + IntToStr(FCount));
NameThreadForDebugging(lThreadName);
{$ENDIF}
while not Terminated do
begin
Sleep(300);
end;
end;
Não se esqueça que esse método só está disponível no Delphi 2010 e, provavelmente, nas versões superiores. No caso do código fonte ser utilizado em versões anteriores, use utilize a diretiva de compilação {$IFDEF VER210} para evitar erro de compilação/compatibilidade.
Apesar desse recurso ser introduzido somente na versão 2010, existe um método que pode ser aplicado para as versões anteriores.
{$IFDEF MSWINDOWS}
procedure SetDebbugerThreadName(const AThreadName: AnsiString; const AThreadID: LongWord = $FFFFFFFF);
type
TThreadNameInfo = record
FType: LongWord; // Deve ser sempre 0x1000
FName: PAnsiChar; // Ponteiro para o nome da thread
FThreadID: LongWord; // Thread ID (-1 indica a corrente thread)
FFlags: LongWord; // Não utilizado, deve ser zero.
end;
var
lThreadInfo: TThreadNameInfo;
begin
lThreadInfo.FType := $1000;
lThreadInfo.FName := PAnsiChar(AThreadName);
lThreadInfo.FThreadID := AThreadID;
lThreadInfo.FFlags := 0;
try
RaiseException($406D1388, 0, SizeOf(lThreadInfo) div SizeOf(LongWord), @lThreadInfo);
except
end;
end;
{$ENDIF}
procedure SetDebbugerThreadName(const AThreadName: AnsiString; const AThreadID: LongWord = $FFFFFFFF);
type
TThreadNameInfo = record
FType: LongWord; // Deve ser sempre 0x1000
FName: PAnsiChar; // Ponteiro para o nome da thread
FThreadID: LongWord; // Thread ID (-1 indica a corrente thread)
FFlags: LongWord; // Não utilizado, deve ser zero.
end;
var
lThreadInfo: TThreadNameInfo;
begin
lThreadInfo.FType := $1000;
lThreadInfo.FName := PAnsiChar(AThreadName);
lThreadInfo.FThreadID := AThreadID;
lThreadInfo.FFlags := 0;
try
RaiseException($406D1388, 0, SizeOf(lThreadInfo) div SizeOf(LongWord), @lThreadInfo);
except
end;
end;
{$ENDIF}
O uso dessa função tem exatamente o mesmo efeito que o método NameThreadForDebugging.
Um exemplo completo utilizando ambas formas pode ser baixada aqui.
Nenhum comentário:
Postar um comentário