[Tutorial] Delphi & Threads

Started by TGA, 25 de November , 2006, 11:55:25 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

TGA

TGA

Bom sei que aqui no forum ja existe um Tuto sobre Threads no delphi, mais resolvi criar um mais explicativo,
segui abaixo também um video demostrando como é simples, boa sorte nos estudos.

Delphi & Threads
Conhecendo a estrutura e o funcionamento de Thread

Bom, vejo muitas pessoas criando programas que realizam processos longos, loops demorados, e que a
aplicação fica travada, impedindo o controle até que o processo realizado seja finalizado, não se pode nem
pausar a operação, e se finalizar, da aquele erro "O programa não está mais respondendo", então, para
resolver isso vamos falar sobre Sincronia de processos, usando a Classe TThread, que permite fazer esse
controle dos processos do sistema, muitas pessoas usam o (Application.ProcessMessages;) mais isso acaba
 deixando a aplicação mais lenta, outros usam timers, ou até cambalacho na aplicação, mais a melhor e mais
viável solução para isso e usando as Threads,  usando Threads nosso programa pode fazer mais de uma
coisa ao mesmo tempo, sem para de responder, isso não é incrível, bom vamos agora ver a estrutura de uma
 Thread;

unit Unit2;

interface

uses
  Classes;

type
  TMinhaThread = class(TThread)
  private

  protected
    procedure Execute; override;
  end;

implementation

procedure TMinhaThread.Execute;
begin

end;

end.


Bom essa é a estrutura simples de uma Thread no delphi, vamos conhecer agora os Atributos da Thread.

Execute: Nesta procedure você inseri os processos que serão executados, os comandos.

Create(CreateSuspended:boolean): Determina se a Thread vai ser criada em um estado suspenso ou não,
usando o parâmetro TRUE a Thread será cria em modo suspenso, (Pausado), usando False, após criada ela
 automaticamente será executada (O parâmetro False não é aconselhável a usar).

Resume: Reinica o Thread;

Suspend: Pausa o Thread
Terminate: Finaliza o Thread;


FreeOnTerminate:  Do tipo Boolean, determina se o Thread vai ser automaticamente destruído após ser finalizada.

Priority: (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical):
Determina qual vai ser a prioridade de execução de sua Thread, é aconselhável usar tpNormal, mais ai vai da
 sua necessidade, cuidado ao usar o  tpTimeCritical , pois se decidir usar esse método ele vai utilizar todo o
tempo possível para se executado,  assim podendo ocupar todo o Sistema Operacional.

Synchronize: Quando temos que acessar ou atualizar alguma VCL através de uma Thread temo que usar o
Synchronize, vou dar uma exemplo, se quiséssemos atualizar o caption da aplicação no meio de uma Thread,
 teríamos que criar um Procedure dentro da Unit Thread e chamar ela pelo Synchronize, veja abaixo um exemplo;

unit Unit2;

interface

uses
  Classes;

type
  TMinhaThread = class(TThread)
  private

  protected
    procedure Execute; override;
   Procedure AtualizaCaption;
  end;

implementation

uses Unit1;

procedure TMinhaThread.Execute;
begin
  synchronize(AtualizaCaption);
end;

Procedure TminhaThread.AtulizaCaption;
begin
  Form1.Caption := 'Minha Thread';
end;

end.


Analisando o código adicionado.

Procedure AtulizaCaption;
Criamos uma Procedure com o nome AtualizaCaption, essa procedure só pode ser executado pela nossa
Thread, criamos ele em modo Protegido.


Procedure TminhaThread.AtulizaCaption;
begin
  Form1.Caption := 'Minha Thread';
end;

Atribuímos em nossa procedure AtualizaCaption, o comando para atualizar o caption da aplicação Form1.


procedure TMinhaThread.Execute;
begin
  synchronize(AtulizaCaption);
end;

Bom, é aqui que nos realmente executamos nossa Procedure criada, utilizando o Synchronize, só
relembrando, dentro de uma Thread quando quisermos acessar alguma VCL, como
( Form1.Caption := 'Minha Thread' ), é de estrema importância realizar este processo como expliquei
anteriormente, se você não usar o Synchronize, sua aplicação poderá até funcionar, mais quando
começar a dar problemas e sua aplicação não responder como deveria, por fazer não vai me xingar, rrsss.


Criando uma Aplicação

Bom agora que já conhecemos a estrutura e alguns atributos de uma Thread vamos começar a codar um
pouco, abra o delphi, se o delphi não abrir um novo projeto faço o seguinte, clique no menu File > New >
Application, adicione um botão no form1, altere o caption do botão para "Criar e Iniciar ", sem aspas.



Agora clique no menu File > New > Other > Thread Object    em Class Name coloque "MinhaThread" sem
aspas, e pressione o botão OK.



Pronto, isso vai criar uma nova Unit, que é a nosso Thread, agora salvamos todo o projeto, de forma que
o a unit do form1 fique como Unit1  e  a Unit da Thread fique como Unit2, provavelmente já esta assim por
padrão. Agora com a Unit2 que é equivalente a Thread aberta vamos inserir uma Variável ( i ) do tipo inteiro,
acima da cláusula implementation, ficando assim:
 
Var
  i : integer; //Variavel de controle

implementation


Em Uses inserimos a biblioteca Sysutils  para usarmos algumas comandos, e também inserimos a Unit1 ,
porque vamos utilizar alguns de seus componentes, no nosso casa vamos acessar o Caption do seu
formulário, deixe a sua Uses como abaixo;

uses
  Classes, Sysutils, Unit1;   //Bibliotecas usadas


Abaixo de protected insira a seguinte procedure, (Procedure AtualizaCaption), ficando assim :

  protected
    procedure Execute; override;
    procedure AtualizaCaption;


Agora vamos inserir o código que atualizara o caption do Form1, após Implementation insira o seguinte código.

procedure MinhaThread.AtualizaCaption;
begin
  form1.Caption := 'Contando :  ' + IntToStr(i);
end;

O que este código acima faz e alterar o caption do Form1 para "Contando : [Valor de i]",
Am, já ia me esquecendo, para que o código acima funcione em baixa de implementation temos que declarar o uses Unit, a final vamos acessar o Fomr1, então para facilitar, vou mostrar todo o código fonte após implementation, para ver como teria que ficar.

implementation

uses Unit1;

procedure MinhaThread.AtualizaCaption;
begin
  form1.Caption := 'Contando :  ' + IntToStr(i);
end;

{ MinhaThread }
procedure MinhaThread.Execute;
begin

end;

end.

Fácio né, agora na procedure MinhaThread.Execute insira o seguinte código.

procedure MinhaThread.Execute;
begin
 for i := 0 to 10000 do
   synchronize(AtualizaCaption);
end;

O código acima faz um loop contando de 0 até 10000, e a cada volta desse loop ele chama o synchronize
mais a função que usa a VCL do form1, no nosso caso a Procedure AtualizaCaption, bom vamos mostrar
o nossa Unit2 (Thread) pronta.

unit Unit2;

interface

uses
  Classes, Sysutils;

type
  MinhaThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    procedure AtualizaCaption;
  end;

Var
  i : integer; //Variavel de controle

implementation

uses Unit1;

procedure MinhaThread.AtualizaCaption;
begin
  form1.Caption := 'Contando :  ' + IntToStr(i);
end;

{ MinhaThread }
procedure MinhaThread.Execute;
begin
 for i := 0 to 10000 do
   synchronize(AtualizaCaption);
end;

end.


Agora vamos aprender a criar e iniciar esse Thread através no nosso Form1, eu poderia criar aqui mesmo
nesta Unit2 a função para Criar a Thread e se auto iniciar quando que apenas chamasse ela de outro lugar,
mais isso irá confundir mais a cabeças de alguém, então vamos ao form1, selecione a Unit1, vamos até a
cláusula Uses e adicionamos a Unit2 que é a biblioteca de nossa Thread, para assim podermos usa-la, agora
a cima da cláusula Implementation declare a seguinte variável (Teste) do tipo MinhaThread, observe como ficou:

var
  Form1: TForm1;
  Teste : MinhaThread;

Implementation


Lembra dos atributos estudados anteriormentes, pois é, agora vamos usalos, volte ao Form1, no evento
OnClick no botão (Criar e Iniciar) insira o seguinte código.

procedure TForm1.Button1Click(Sender: TObject);
begin
 Teste := MinhaThread.Create(true);
 Teste.FreeOnTerminate := true;
 Teste.Priority := tpNormal;
 Teste.Resume;
end;


Explicando:
Teste := MinhaThread.Create(true);      Cria a Thread em Pause, (Cria mais não executa).
Teste.FreeOnTerminate := true;             Após a Thread terminar ela será Finalizada.
Teste.Priority := tpNormal;                      Prioridade da Thread, usei o tipo Normal mesmo.
Teste.Resume;                                       Iniciar / Continua a Thread;


Agora podemos testar, salve a aplicação para não perder o que fez até aqui, compile execute e clique no
 botão "Criar e Iniciar" faça os testes, vai ver como a aplicação vai rodar livremente, poderá usar outros
processos sem problemas, bom acho que deu para entender como funciona, agora sabendo que se eu usar
 o comando Suspend eu pauso, e o comando Resume eu continuo uma Thread, faço o seguinte, coloque
 mais dois botões no Form1, (Pausar, Continuar) no OnClick do pausar coloque o seguinte, Teste.Suspend,
e no OnClik do Continuar insira o seguinte, Teste.resume, tenho certeza que vai adorar o efeito, faça os
testes, galera, boa sorte nos estudos, já é tarde, chega de escrever, abraços..


Download do Video
http://rapidshare.com/files/4764853/Thread_TGA.rar.html
"A IMAGINAÇÃO É MAIS IMPORTANTE QUE O CONHECIMENTO"
__________________________________________________________

shake

TGA perfeito!
Parabéns cara pelo tuto e pelo vídeo!
Ficou massa d+ agora sim deu pra aprender a fazer uma Thread, muito bem explicado!

Abraços!

Hacker Xtreme

Mano eu acabei de ler, cara ta show! Achei louco, sem contar que o TGA Send Spam 0.2 foi feito assim Thread.Pause, Thread.Resume e etc né ? Ficou muito louco o vídeo e tutorial, parabéns cara pelos estudos e obrigado por ta ajudando os iniciantes em delphi que nem eu :P!

...by Xtreme

Ðark$pawn


TGA

TGA

Que bom que gostaram..  ;)
vlw .. abraços..
"A IMAGINAÇÃO É MAIS IMPORTANTE QUE O CONHECIMENTO"
__________________________________________________________

Quicky

Nice kra
vou retomar alguns projetos ^^
agora entendo pq akele client ftp lagava todo o.O
vlw kra =]
Just Me...