Na maioria das vezes que precisamos criar uma thread, é devido a dois casos de uso:
- Executar uma unidade de trabalho, com início e fim.
- Executar um trabalho contínuo, em intervalos, sem fim definido.
As threads funcionam da seguinte maneira: Definimos o trabalho que será executado no método Execute.
protected
procedure Execute; override;
Ao chegar no fim desse método, a thread conclui seu trabalho, e fica pronta para ser destruída.
Para criar uma thread, definimos uma classe nova que herda da classe TThread, definimos o nosso construtor e destrutor, definimos o execute, e colocamos a nossa regra de negócio.
Exemplo:
TMinhaThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
Uma thread inicia seu trabalho ao chamarmos o método Start. Entretanto, no Delphi a thread ao ser criada com o construtor default da classe TThread, inicia seu trabalho imediatamente, sem necessidade de chamar o Start. Para evitarmos esse comportamento, definimos o construtor da nossa classe para chamar o construtor da classe TThread que aceita um parâmetro que indica se ela deve iniciar suspensa. Passamos o valor True nesse parâmetro:
constructor TMinhaThread.Create;
begin
inherited Create(True);
end;
Assim a thread só iniciará se chamarmos Start. Isso nos dá várias vantagens, por exemplo, adiar o início do trabalho da thread para quando quisermos.
Após a thread terminar seu trabalho, podemos então destruí-la. Mas como sabemos que a thread terminou seu trabalho? A classe TThread possui um método chamado WaitFor, que faz o processamento esperar a thread terminar. Assim, se chamarmos WaitFor, nosso programa vai parar até que a thread chegue no fim de seu método Execute.
procedure TMinhaThread.Execute;
begin
inherited;
// Faz um Trabalho
end; // Espera do WaitFor acaba aqui
Mas quando nossa thread implementa o caso 2, ou seja, um trabalho contínuo, executado em intervalos e sem um fim definido, então nosso WaitFor esperaria infinitamente:
procedure TMinhaThread.Execute;
begin
inherited;
While True do
begin
Sleep(Intervalo);
// Faz Trabalho
end;
end; // Nunca vai chegar aqui, WaitFor esperaria para sempre
Então, nesse caso, temos que usar uma flag definida na classe TThread chamada Terminated. Teríamos que fazer nosso while verificar essa flag:
procedure TMinhaThread.Execute;
begin
inherited;
While not Terminated do
begin
Sleep(Intervalo);
// Faz Trabalho
end;
end;
Assim, antes de chamarmos WaitFor, devemos setar essa flag com True, ou chamar o método Terminate, e então não ficaremos travados no WaitFor.
Independente de qual caso estamos implementando, é uma boa prática sempre chamarmos a seguinte sequência de métodos quando queremos encerrar a thread:
Terminate;
WaitFor;
Free;
Jamais devemos chamar o método TerminateThread do Windows; ele mata a thread forçadamente, e ela não liberaria seus recursos, causando memory leak.
Comentários
1 comentário
Matéria muito esclarecedora, objetiva e sem "firulas"....
Parabéns !!!!!!
Por favor, entre para comentar.