Clique para saber mais...
  Home     Download     Produtos / Cursos     Revista     Vídeo Aulas     Fórum     Contato   Clique aqui para logar | 12 de Junho de 2026
  Login

Codinome
Senha
Salvar informações

 Esqueci minha senha
 Novo Cadastro

  Usuários
100 Usuários Online

  Revista ActiveDelphi
 Assine Já!
 Edições
 Sobre a Revista

  Conteúdo
 Apostilas
 Artigos
 Componentes
 Dicas
 News
 Programas / Exemplos
 Vídeo Aulas

  Serviços
 Active News
 Fórum
 Produtos / Cursos

  Outros
 Colunistas
 Contato
 Top 10

  Publicidade

  [Artigos]  Threads no Delphi, por onde começar ? – Parte III
Publicado por rboaro : Quinta, Fevereiro 21, 2013 - 09:06 GMT-3 (586 leituras)
Comentários comentar   Enviar esta notícia a um amigo Enviar para um amigo   Versão para Impressão Versão para impressão
Diego Garcia Então vamos lá, ver um pouco mais sobre as Threads no Delphi. Nessa terceira parte, veremos como criar blocos protegidos em uma thread para, entre outras coisas, interagir com a GUI (Graphical User Interface) com uma maior segurança. Com o intuito de simplificar o estudo, faremos o já clássico exemplo das barras de progressão sendo manipuladas paralelamente.

Basicamente nosso exemplo será uma thread que receberá o ponteiro de um TProgressBar. Essa thread irá setar a posição do TProgressBar em zero e depois fará um laço onde o TProgressBar será preenchido até a sua posição final (propriedade max). Seguindo a linha de raciocínio da primeira parte do estudo, vamos criar uma nova thread com a seguinte estrutura:
type
TProcInThread = class(TThread)
private
FPgbProgresso : TProgressBar;
procedure atualizarProgressBar;
procedure avancarProgressBar;
public
constructor Create(CreateSuspended : boolean; pgbProgresso : TProgressBar);
protected
procedure Execute; override;
end;
Seguindo a mesma lógica dos posts anteriores, nosso construtor não apresenta nenhuma novidade:
constructor TProcInThread.Create(CreateSuspended : boolean;pgbProgresso: TProgressBar);
begin
Self.FPgbProgresso := pgbProgresso;
inherited Create(CreateSuspended);
end;
O método avançarProgressBar() foi feito mais por uma questão de conveniência, porém, entrarei em maiores detalhes em um próximo post:

procedure TProcInThread.avancarProgressBar;
begin
Self.FPgbProgresso.StepBy(1);
end;
O método Execute() também não possui nada demais, somente a chamada para o método atualizarProgressBar(), onde toda nossa lógica vai estar:

procedure TProcInThread.Execute;
begin
atualizarProgressBar();
end;
Agora sim, vamos ver o método mais importante da nossa thread, o atualizarProgressBar():

procedure TProcInThread.atualizarProgressBar;
var
I: Integer;
begin
Self.FPgbProgresso.Position := 0;
for I := 0 to Self.FPgbProgresso.Max - 1 do
begin
if Self.Terminated then
abort();
Synchronize(Self.avancarProgressBar);
Sleep(100);
end;
end;
Coloquei o Sleep(100) para que fosse possível visualizar melhor a execução, fora isso, chegamos finalmente no X da questão, o método Synchronize(). Este método executa a chamada de um determinado método (passado como parâmetro) dentro da thread principal da aplicação (main thread), ou seja, seguindo o nosso exemplo, o comando :

Synchronize(Self.avancarProgressBar);
Faz com que o método avancarProgressBar() seja executado dentro da thread principal da aplicação, fazendo com que o procedimento do método seja protegido e não entre em conflito com outras threads que manipulem os mesmos dados que a thread atual.

Com isso, nossa thread já está pronta. Para vê-la em execução, vamos criar uma formulário com 3 TProgressBar e 2 TButtons. No private do formulário, crie 3 objetos do tipoTProcInThread que é a classe da nossa thread:

type
TForm1 = class(TForm)
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
ProgressBar3: TProgressBar;
Button1: TButton;
Button2: TButton;
private
oProcInThread1 : TProcInThread;
oProcInThread2 : TProcInThread;
oProcInThread3 : TProcInThread;
public
end;
Sete a propriedade Max dos TProgressBar em 50 e no Button1 faremos a iniciação das threads:

procedure TForm1.Button1Click(Sender: TObject);
begin
oProcInThread1 := TProcInThread.Create(true,ProgressBar1);
oProcInThread2 := TProcInThread.Create(true,ProgressBar2);
oProcInThread3 := TProcInThread.Create(false,ProgressBar3);

oProcInThread1.Start;

oProcInThread2.FreeOnTerminate := true;
oProcInThread2.Start;
end;
Note que a terceira thread (oProcInThread3) não foi criada como Suspended, sendo assim não é necessário chamar o método Start() para iniciar a execução da thread e a segunda thread (oProcInTread2) foi configurada para ser liberada da memória assim que termine sua execução.

Agora em nosso Button2, liberaremos as threads da memória, mas somente as que não são liberadas automaticamente:

if not oProcInThreadBarra2.Finished then
oProcInThreadBarra2.WaitFor();
FreeAndNil(oProcInThreadBarra2);

if not oProcInThreadBarra3.Finished then
oProcInThreadBarra3.WaitFor();
FreeAndNil(oProcInThreadBarra3);

Finalmente, basta executar o aplicativo e ver o resultado:




O uso de blocos protegidos em um ambiente multi-thread é uma questão muito delicada, não proteger seus blocos que possuam acesso a dados compartilhados (como por exemplo um objeto, uma tabela ou um componente visual) abre margem para a ocorrência de conflitos, enquanto que o ato de proteger muitos blocos (utilizando o synchronize() por exemplo) pode comprometer o desempenho da sua aplicação. As boas práticas recomendam que evitem ao máximo compartilhar recursos entre as threads e nos casos que não for possível, existem algumas técnicas para se fazer.
Eu particularmente não recomendo o uso do synchronize() se a intenção não seja interagir com componentes visuais, caso seja necessário proteger um bloco crítico existem outras opções como por exemplo o TCriticalSection ou o TMutex que serão temas para posts futuros.
Na próxima etapa do estudo, veremos um pouco sobre AnonymousThread e métodos anônimos.


Comentários Comentários
   Ordem:  
Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos.
  Edição 112

Revista ActiveDelphi

  50 Programas Fontes


  Produtos

Conheça Nossos Produtos

Copyright© 2001-2016 – Active Delphi – Todos os direitos reservados