Problema com Thread
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:
Aqui esta a chamada:
Alguma sugestão?
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
Curtidas 0
Melhor post
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...
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
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
Dê uma olhada neste artigo: http://www.planetadelphi.com.br/dica/6353/construindo-threads-com-delphi
GOSTEI 0
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.
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
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
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
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.
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
14/03/2013
De forma simples, acredito que você terá que fazer uso de uma fila.
GOSTEI 0
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
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...
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
14/03/2013
Fico no aguardo do resultado.
GOSTEI 0
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!
Incrementando uma variável e cada nova instancia e decrementando no termino da execução...
Grato!
GOSTEI 0
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!
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