Páginas filhas
  • Lentidão em processamento de integrações rotinas Delphi

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Problema

Temos diversas rotinas desenvolvidas em Delphi executando integrações variadas, onde aquelas no qual realiza geração de arquivos com base em layout com informações como por exemplo vendas, NF, produtos, clientes, estoque, etc; eventualmente apresenta alguns problemas de lentidão e travamentos nesses processos devido o grande volume de dados da base de dados necessários para tal tarefas.

Solução

Painel
bgColor#fff

Neste post, vou mostrar um exemplo bastante básico de como criar um processamento usando Thread em Delphi, isso resolve o problema pois passa a execução da consulta e montagem de arquivo para uma Thread separada da Thread principal do Form da tela.

1 - Primeiro crie uma nova classe para a Thread no Delphi, menu File -> New -> Other -> Thread Object para criar a Thread mas isso depende da versão do Delphi. O esqueleto gerado será basicamente o reproduzido abaixo:

Bloco de código
TWProcessamentoThread = class(TThread)
protected
procedure Execute; override;
end;


2 - O código gerado não sobrescreve o construtor padrão. Como teremos uma interação com o Form principal da aplicação, será preciso montar um construtor especial que aceite o nosso Form como parâmetro:

Bloco de código
var _Form: TForm;

constructor TWProcessamentoThread.Create(CreateSuspended: Boolean; AForm: TForm);
begin
  inherited Create (CreateSuspended);
  _Form := AForm;
  FreeOnTerminate := false;
end;


A primeira linha do construtor chama o construtor Create da classe base (inherited) passando-lhe o parâmetro para indicar se a thread deve iniciar imediatamente ou permanecer suspensa. FreeOnTerminate é ajustado como false de modo que nós teremos que destruir instâncias da classe manualmente.

3 - A procedure Execute é onde deve ficar o código executado pela Thread. Aqui onde e criado a variável uFormPrincipal esta acessando o Form principal para obter os filtros inseridos pelo cliente, e nessa procedure será implementado o comportamento da Thread.

Bloco de código
procedure TWProcessamentoThread.Execute;
var uFormPrincipal : TfrmPrincipal;
begin
  uFormPrincipal := _Form As TfrmPrincipal;
  // Implementação das consultas e geração de arquivos
end;


4 - No seu Form principal ao clique do botão Iniciar o processo crie uma instância da Thread para execução imediata e implemente um TTimer no Form principal com intervalo de um segundo ligando o Timer que checa o status da execução dela assim que instanciar a Thread:

Bloco de código
var _Thread: ThreadProcesso;


_Thread := TWProcessamentoThread.Create (false, Self);
Timer1.Enabled := true;


Na classe da Thread crie uma variável concluiuProcessamento do tipo boolean e passe ela para true no final do processamento. 

5 - No evento do Timer do Form principal, verificamos se a Thread chegou ao fim da execução para fazer a limpeza:

Bloco de código
if (_Thread.concluiuProcessamento) then begin
  Timer1.Enabled := false;
  _Thread.Free;
  _Thread := Nil;
end;


6 - Muito importante matar a Thread se o cliente fechar a rotina antes de concluir, para isso no Form principal no evento de saída FormDestroy implemente o trecho abaixo.

Bloco de código
 if TimerThread.Enabled then
    _Thread.Terminate; 



Artigos relacionados