Problema com Thread
14/03/2013
0
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
Post mais votado
14/03/2013
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...
Luiz Menin
Mais Posts
14/03/2013
Luiz Menin
Dê uma olhada neste artigo: http://www.planetadelphi.com.br/dica/6353/construindo-threads-com-delphi
14/03/2013
Francisco Macário
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.
14/03/2013
Km Sistemas
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?
14/03/2013
Km Sistemas
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...
14/03/2013
Francisco Macário
14/03/2013
Francisco Macário
14/03/2013
Km Sistemas
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!
18/11/2015
Km Sistemas
Incrementando uma variável e cada nova instancia e decrementando no termino da execução...
Grato!
18/11/2015
Luiz Menin
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.
Clique aqui para fazer login e interagir na Comunidade :)