Threads são na realidade um processamento paralelo ao sistema. Como trabalhamos na grande maioria das vezes com computadores mono-processados, quando criamos multi-threads estamos então trabalhando com o conceito de multi-tarefas. Caso o computador seja multi-processado, as threads seriam distribuídas entre estes processadores. Visando facilitar a vida de outras pessoas, pensei em escrever o (pouco) conhecimento que tenho sobre o assunto. Sendo assim, "bora escovar bits".
Passo 1 - Criando uma nova Thread.
Para iniciar uma nova thread, vá ao menu File
-> New -> Other, em "Delphi Files" selecione "Thread Object".

Figura 1 - Menu para criar a nova Thread
A partir deste ponto, o Borland Developer Studio (chamarei daqui para frente
de BDS) monta um esqueleto de uma thread. Esqueleto este que já vem
comentado:

Figura 2 - Esqueleto da Thread
Tradução do Comentário:
{ Importante: Métodos e propriedades de objetos em componentes visuais só podem ser
usados através do método chamado Synchronize, por exemplo,
Synchronize(UpdateCaption);
e UpdateCaption poderia ser algo como,
procedimento TThread.UpdateCaption;
begin
Form1.Caption := ' Atualizou em uma thread';
end; }
Passo 2 - Criando funcionalidade para thread.
A partir deste ponto, já sabemos que o código a ser executado
em uma thread, deve ser inserido na procedure Execute, e caso haja um código
que acesse componentes visuais (VCL), este deve ser executado através
da procedure Synchronize.
Para ficar mais fácil a compreensão, construirei um exemplo que
faça acesso a componentes visuais.
Para teste de atualização de dados na tela, podemos ver como
deve ser o código de uma thread que acessa a VCL:
Figura 3 - Unit da Thread
Com o código acima podemos verificar o seguinte:
- Foi criado uma procedure "Atualiza", onde esta será responsável
pela atualização de componentes VCL;
- Quando for necessário executar o código de atualização,
a procedure será executa a partir de Synchronize;
- O código que se deseja executar nas threads devem ficar na procedure
execute;
- É importante verificar o estado de Terminated antes de executar
um processo na thread.
Tendo em vista agora que já sabemos o que é necessário
para ter uma thread, vamos criar nosso Form para controlar esta thread. Deverá ficar
semelhante a imagem
abaixo:

Figura 4 - Formulário Principal
Segue abaixo
os códigos da nossa janela principal:
procedure TFMain.BtnCreateClick(Sender: TObject);
begin
//-- False - Cria a Thread em execução
//-- True - Cria a Thread suspensa
MyThread:= TMyThread.Create(True);
MyThread.Priority:= Prioridade;
//-- Atribui um procedimento ao terminar
//-- a execução da thread
MyThread.OnTerminate:= MyTerminate;
MyThread.Resume;
//-- Hora iniciado a thread
LblHoraIniciada.Caption := FormatDateTime('hh:nn:ss:zzz',Now);
AtualizaButtons;
end;
procedure TFMain.BtnSuspendClick(Sender: TObject);
begin
//-- Pausa a execução da thread
MyThread.Suspend;
AtualizaButtons;
end;
procedure TFMain.BtnResumeClick(Sender: TObject);
begin
//-- Retorna a execução da thread
MyThread.Resume;
AtualizaButtons;
end;
procedure TFMain.BtnTerminateClick(Sender: TObject);
begin
//-- Encerra a execução da thread
MyThread.Terminate;
MyThread := nil;
AtualizaButtons;
end;
procedure TFMain.AtualizaButtons;
begin
BtnCreate.Enabled := not Assigned(MyThread);
BtnSuspend.Enabled := (Assigned(MyThread))and (not MyThread.Suspended);
BtnResume.Enabled := (Assigned(MyThread))and (MyThread.Suspended);
BtnTerminate.Enabled := Assigned(MyThread);
end;
procedure TFMain.CBPriorityClick(Sender: TObject);
begin
Case CBPriority.ItemIndex of
0 : Prioridade:= tpIdle;
1 : Prioridade:= tpLowest;
2 : Prioridade:= tpLower;
3 : Prioridade:= tpNormal;
4 : Prioridade:= tpHigher;
5 : Prioridade:= tpHighest;
6 : Prioridade:= tpTimeCritical;
end;
end;
procedure TFMain.FormCreate(Sender: TObject);
begin
Prioridade := tpIdle;
end;
procedure TFMain.MyTerminate(Sender: TObject);
begin
MyThread:= nil;
AtualizaButtons;
LblHoraFinalizada.Caption := FormatDateTime('hh:nn:ss:zzz',Now);
end;
Conclusão
Da maneira que foi desenvolvido, este sistema serve para demonstrar os principais
métodos de threads, desde a criação, destruição,
pausa e resumo. Vale destacar a criação e destruição
de uma thread, vejamos algumas características:
- Existe a possibilidade de criar uma thread de modo suspenso, sendo assim,
a medida que uma thread é criada, ela só será executada
após a chamada do método Resume;
- Logicamente, também existe a possibilidade de criar uma thread
em modo de execução, descartando a necessidade de execução
do método execute;
- É
possível também definir um procedimento personalizado a ser executado
após o término da execução da thread, basta analisar
o exemplo acima para facilitar o entendimento;
- Não é necessário definir um método
para ser executado no término da execução da thread,
sendo que para isto se faz necessário atribuir True para o atributo
FreeOnTerminate.
Finalizo por aqui, e espero ter chance de poder escrever um próximo
artigo, sendo este, discutindo sobre execução de threads paralelas.
Tive como única finalidade ao escrever este artigo, ser claro o suficiente
a ponto de que, com somente este material, fosse possível a um programador
delphi (até mesmo iniciante), desenvolver uma aplicação
que fizesse uso de thread.
Anderson de Oliveira Leite
Programador delphi
|