Problema com Thread

Delphi

14/03/2013

Olá...

Tenho uma Thread em minha aplicação que faz envio de Email!
porem esta Thread usa os componentes que estão na tela que chamou a Thread!
o problema esta na seguinte situação:
da minha tela principal chamo o método da Thread varias vezes, pois o cliente vai clicando em enviar Email e o sistema vai chamando a Thread para enviar o Email...
ou seja, varias instancias ficam tentando enviar o Email!

quando meu cliente fecha a tela principal, todos os emails que ainda não foram enviados pois a Thread ainda não terminou a execução não serão enviados!
preciso impedir meu cliente de fechar a tela principal enquanto todas as threads não terminarem suas execuções!




aqui esta o código da minha Thread:
unit Thread;

interface

uses
  Classes, spdNFe, ActiveX, FatNFE, clipbrd, SysUtils;

type
  Enviaemail = class(TThread)
  private
     Nfeenvia: TspdNFe;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    constructor enviar(Nfe: TspdNFe; SID_nota, SID_Numero : String);
  end;

var
  SIdentificador, SNumero : string;

implementation

{ Enviaemail }

constructor Enviaemail.enviar(Nfe: TspdNFe; SID_nota, SID_Numero : String);
begin
  Create(False);
  Nfeenvia := Nfe;
  SIdentificador := SID_nota;
  SNumero        := SID_Numero;
  FreeOnTerminate := True;
  WaitFor;
end;

procedure Enviaemail.Execute;
begin
  CoInitialize(nil);
  Try
     Nfeenvia.EnviarNotaDestinatario(SIdentificador);
     Form_NFe.RzStatusPane_Informa.Caption := 'Email da Nota: '+SNumero+' enviado com sucesso  ';
     Form_NFe.RzRichEdit_LogEmail.Lines.Add('Email da Nota: '+SNumero+' enviado com sucesso  ');
     //FatNFE.SStatus := 'Enviado com Sucesso';
  Except
    on E: Exception do
    begin
      Form_NFe.RzStatusPane_Informa.Caption := 'Erro ao enviar o Email da Nota: '+SNumero+'  ';
      Form_NFe.RzRichEdit_LogEmail.Lines.Add('Erro ao enviar o Email da Nota: '+SNumero+'  ');
      Form_NFe.RzStatusPane_Informa.Blinking := True;
      //FatNFE.SStatus := 'Erro ao enviar nota';
      Clipboard.AsText := E.message;
    end;
  end;
  { Place thread code here }
end;

end.




Aqui esta a chamada:
procedure TForm_NFE.vClick(Sender: TObject);
var
  email : EnviaEmail;
begin
  try
    email := EnviaEmail.enviar(NFe, Q_Notas_Prontasid_a03.AsString, Q_Notas_Prontasnnf_b08.AsString);
  except
    on E: Exception do
      begin
        ShowMessage('Atenção: Falha no Email.' +
                     #13 + E.Message);
        raise;
      end;
  end;
end;



Alguma sugestão?
Km Sistemas

Km Sistemas

Curtidas 0

Melhor post

Luiz Menin

Luiz Menin

14/03/2013

É complicado, pois você vai criando uma thread para cara click. Eu utilizo threads de uma forma totalmente diferente, não fecho ela nunca durante a aplicação.
Você poderia utilizar uma especie de contador, que a cada thread criada, adicione um neste contador. No momento em que envia o email, diminui um.
Na tentativa de fechar o form, você verifica se este contador é maior que zero.
É só uma ideia...
GOSTEI 1

Mais Respostas

Luiz Menin

Luiz Menin

14/03/2013

Você deve utilizar o método Synchronize.
Dê uma olhada neste artigo: http://www.planetadelphi.com.br/dica/6353/construindo-threads-com-delphi
GOSTEI 0
Francisco Macário

Francisco Macário

14/03/2013

Olá.

Bom para impedir o fechamento do FORM utilize o evento OnCloseQuery do FORM, fazendo uso da variavel CanClose.

Exemplo disponivel em Planeta Delphi >
[url]http://www.planetadelphi.com.br/dica/4179/impedir-que-o-form-seja-fechado-com-alt+f4[/url]

Assim voce so deixara CanClose = true caso nao exista nenhum Thread em execução.

Para isso implemente algum tipo de controle, como um contador, etc.

Espero que ajude.
GOSTEI 0
Km Sistemas

Km Sistemas

14/03/2013

Você deve utilizar o método Synchronize.
Dê uma olhada neste artigo: http://www.planetadelphi.com.br/dica/6353/construindo-threads-com-delphi



Alterei o código da Thread para ficar da seguinte forma:

unit Thread;

interface

uses
  Classes, spdNFe, ActiveX, FatNFE, clipbrd, SysUtils;

type
  Enviaemail = class(TThread)
  private
     Nfeenvia: TspdNFe;
     msg: String;
    { Private declarations }
  protected
    procedure Execute; override;
    procedure IncLabel; virtual;
  public
    constructor enviar(Nfe: TspdNFe; SID_nota, SID_Numero : String);
  end;

var
  SIdentificador, SNumero : string;

implementation

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure Enviaemail.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ Enviaemail }

constructor Enviaemail.enviar(Nfe: TspdNFe; SID_nota, SID_Numero : String);
begin
  Create(False);
  Nfeenvia := Nfe;
  SIdentificador := SID_nota;
  SNumero        := SID_Numero;
  FreeOnTerminate := True;
end;

procedure Enviaemail.Execute;
begin
  CoInitialize(nil);
  Try
     Nfeenvia.EnviarNotaDestinatario(SIdentificador);
     msg := 'Email da Nota: '+SNumero+' enviado com sucesso  ';
     Synchronize(IncLabel);
     //Form_NFe.RzStatusPane_Informa.Caption := 'Email da Nota: '+SNumero+' enviado com sucesso  ';
     //Form_NFe.RzRichEdit_LogEmail.Lines.Add('Email da Nota: '+SNumero+' enviado com sucesso  ');
  Except
    on E: Exception do
    begin
      msg := 'Erro ao enviar o Email da Nota: '+SNumero+'  ';
      //Form_NFe.RzStatusPane_Informa.Caption := 'Erro ao enviar o Email da Nota: '+SNumero+'  ';
      //Form_NFe.RzRichEdit_LogEmail.Lines.Add('Erro ao enviar o Email da Nota: '+SNumero+'  ');
      Form_NFe.RzStatusPane_Informa.Blinking := True;
      Clipboard.AsText := E.message;
    end;
  end;
  { Place thread code here }
end;

procedure Enviaemail.IncLabel;
begin
   Form_NFe.RzStatusPane_Informa.Caption := msg;
   Form_NFe.RzRichEdit_LogEmail.Lines.Add(msg);
  { o Contador será executado em modo protegido por uma Seção Critica do Windows}
end;

end.


Porém ainda continua fechando a tela sem terminar de enviar os Email's!
Como faço para verificar se ainda tem alguma Thread sendo executada?
GOSTEI 0
Km Sistemas

Km Sistemas

14/03/2013

Olá.

Bom para impedir o fechamento do FORM utilize o evento OnCloseQuery do FORM, fazendo uso da variavel CanClose.

Exemplo disponivel em Planeta Delphi >
[url]http://www.planetadelphi.com.br/dica/4179/impedir-que-o-form-seja-fechado-com-alt+f4[/url]

Assim voce so deixara CanClose = true caso nao exista nenhum Thread em execução.

Para isso implemente algum tipo de controle, como um contador, etc.

Espero que ajude.


Com relação a impedir a form de fechar ta tranquilo... o problema é saber quando pode fechar?
Ou seja, todas as instancias da Thread já terminaram sua execução...
GOSTEI 0
Francisco Macário

Francisco Macário

14/03/2013

De forma simples, acredito que você terá que fazer uso de uma fila.
GOSTEI 0
Francisco Macário

Francisco Macário

14/03/2013

Para esta tarefa eu criaria um robô, usando uma fila. Para cada NF-e autorizada ele processaria o envio do email.

GOSTEI 0
Km Sistemas

Km Sistemas

14/03/2013

É complicado, pois você vai criando uma thread para cara click. Eu utilizo threads de uma forma totalmente diferente, não fecho ela nunca durante a aplicação.
Você poderia utilizar uma especie de contador, que a cada thread criada, adicione um neste contador. No momento em que envia o email, diminui um.
Na tentativa de fechar o form, você verifica se este contador é maior que zero.
É só uma ideia...


Essa ideia parece ser simples de implementar! Vou tentar fazer desta forma!
GOSTEI 0
Luiz Menin

Luiz Menin

14/03/2013

Fico no aguardo do resultado.
GOSTEI 0
Km Sistemas

Km Sistemas

14/03/2013

Eu sei que já faz um bom tempo mas apenas para manter documentado a solução proposta pelo Luiz Antônio Menin resolveu meu problema!
Incrementando uma variável e cada nova instancia e decrementando no termino da execução...
Grato!
GOSTEI 0
Luiz Menin

Luiz Menin

14/03/2013

Eu sei que já faz um bom tempo mas apenas para manter documentado a solução proposta pelo Luiz Antônio Menin resolveu meu problema!
Incrementando uma variável e cada nova instancia e decrementando no termino da execução...
Grato!


Fico feliz pelo feedback e por você ter conseguido resolver!
Obrigado.
GOSTEI 1
POSTAR