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