none
Manipulamento de Threads RRS feed

  • Pergunta

  • Olá a todos
    Estou desenvolvendo um programa (em C#) e atualmente estou implementando uma função que envia emails, dentro dessa função eu inicio um thread antes de enviar o email, esse thread faz com que um outro form apareça com a mensagem de que o email esta sendo enviado, enquanto o formulário principal manda o email. Até ai tudo bem, o meu problema é que depois que o email é enviado eu não consigo fechar o outro form. Alguém poderia me dar uma ajuda?
    Desde Já Grato.
    terça-feira, 5 de julho de 2011 14:41

Respostas

  • Dante158,

    Acho que neste caso, o melhor seria você enviar o e-mail de forma assíncrona, ao invés de criar o form em uma Thread separada.

    Assim você não terá problemas de chamadas entre forms em threads diferentes.

    No seu caso, seria tipo:

     

     public void EnviarEmail(string strDestino, string strAssunto, string strCorpo, string strAnexo)
     {
      MailMessage message = new MailMessage();
      message.To.Add(strDestino);
      Attachment anexo = new Attachment(strAnexo);
      message.Attachments.Add(anexo);
      message.Subject = strAssunto;
      message.From = new MailAddress("email@gmail.com");
      message.Body = strCorpo;
      SmtpClient smtp = new SmtpClient();
      smtp.Host = "smtp.gmail.com";
      smtp.EnableSsl = true;
      smtp.Credentials = new System.Net.NetworkCredential("email@gmail.com", "***");
      try
      {
      // cria e mostra o form...
      frmEmail Email = new frmEmail();
      Email.Show();
    
      // cria o ManualResetEvent para fechar o form quando terminar de enviar o email...
      using (ManualResetEvent resetEvent = new ManualResetEvent(false))
      {
       // pluga o SendComplete para saber quando terminou de enviar o e-mail...
       smtp.SendCompleted += new SendCompletedEventHandler(OnSmtpSendCompleted);
    
       // faz o envio assíncrono...
       smtp.SendAsync(message, resetEvent);
    
       // aguarda o término do envio...
       resetEvent.WaitOne();
      }
    
      // fecha o form...
      Email.Close();
      }
      catch (Exception ex)
      {
      MessageBox.Show(ex.Message);
      }
     }
    
     private void OnSmtpSendCompleted(object sender, AsyncCompletedEventArgs e)
     {
      // pega o ManualResetEvent para indicar para a Thread principal que o email foi enviado...
      ManualResetEvent resetEvent = (ManualResetEvent)e.UserState;
      resetEvent.Set();
    
      // verifica se deu algum erro e mostra o dialogo...
      if(e.Error != null)
      MessageBox.Show(e.Error.Message);
      else MessageBox.Show("Mensagem enviada com sucesso");
     } 
    

     

    at.,


    Rogério de Resende Ohashi | Ohashi.NET (.NET, Security, C#, WinForms, WCF, Workflow, Azure, Windows Phone, Mono)
    segunda-feira, 11 de julho de 2011 20:33
    Moderador

Todas as Respostas

  • Prezado,

    Não sei exatamente como você fez essa implementação, mas, uma saída que funcionaria em qualquer situação seria procurar o seu Form na propriedade Application.OpenForms:

    http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx

    Aí é só fechar ele...


    André Alves de Lima
    Microsoft MVP - Client App Dev
    Visite o meu site: http://www.andrealveslima.com.br
    Me siga no Twitter: @andrealveslima
    terça-feira, 5 de julho de 2011 18:18
    Moderador
  • Prezado,

    Não sei exatamente como você fez essa implementação, mas, uma saída que funcionaria em qualquer situação seria procurar o seu Form na propriedade Application.OpenForms:

    http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx

    Aí é só fechar ele...


    André Alves de Lima
    Microsoft MVP - Client App Dev
    Visite o meu site: http://www.andrealveslima.com.br
    Me siga no Twitter: @andrealveslima
    Eu fiz da seguinte forma:
    public void EnviarEmail(string strDestino, string strAssunto, string strCorpo, string strAnexo)
        {
          MailMessage message = new MailMessage();
          message.To.Add(strDestino);
          Attachment anexo = new Attachment(strAnexo);
          message.Attachments.Add(anexo);
          message.Subject = strAssunto;
          message.From = new MailAddress("email@gmail.com");
          message.Body = strCorpo;
          SmtpClient smtp = new SmtpClient();
          smtp.Host = "smtp.gmail.com";
          smtp.EnableSsl = true;
          smtp.Credentials = new System.Net.NetworkCredential("email@gmail.com", "***");
          try
          {
    
            Thread trdAviso = new Thread(AvisoEmail);
            trdAviso.IsBackground = true;
            trdAviso.Start();
            smtp.Send(message);
            MessageBox.Show("Mensagem enviada com sucesso");
            Application.OpenForms["frmEmail"].Close();
          }
          catch (Exception ex)
          {
            MessageBox.Show(ex.Message);
            Application.OpenForms["frmEmail"].Close();
          }
        }
        private void AvisoEmail()
        {
          frmEmail Email = new frmEmail();
          Email.Show();
        }
    


    E quando eu tento fecha o formulário pela coleção de formulários abertos na aplicação ocorre a seguinte exeção: "Operação entre threads inválida: controle 'frmEmail' acessado de um thread que não é aquele no qual foi criado."

    terça-feira, 5 de julho de 2011 20:08
  • Coloca o Application.OpenForms["frmEmail"].Close(); no fim do método AvisoEmail(); 

    private void AvisoEmail()
      {
       frmEmail Email = new frmEmail();
       Email.Show();
       Application.OpenForms["frmEmail"].Close();
    
    }

    Se a resposta foi útil pra você, colabore com o fórum marcando como resposta esta sugestão, obrigado!

    Júlio Cesar Cosmo, MCP, MCTS - Influenciador Sharepoint, Influenciadores Microsoft

    http://juliocosmo.wordpress.com

    segunda-feira, 11 de julho de 2011 11:53
  • Dante158,

    Acho que neste caso, o melhor seria você enviar o e-mail de forma assíncrona, ao invés de criar o form em uma Thread separada.

    Assim você não terá problemas de chamadas entre forms em threads diferentes.

    No seu caso, seria tipo:

     

     public void EnviarEmail(string strDestino, string strAssunto, string strCorpo, string strAnexo)
     {
      MailMessage message = new MailMessage();
      message.To.Add(strDestino);
      Attachment anexo = new Attachment(strAnexo);
      message.Attachments.Add(anexo);
      message.Subject = strAssunto;
      message.From = new MailAddress("email@gmail.com");
      message.Body = strCorpo;
      SmtpClient smtp = new SmtpClient();
      smtp.Host = "smtp.gmail.com";
      smtp.EnableSsl = true;
      smtp.Credentials = new System.Net.NetworkCredential("email@gmail.com", "***");
      try
      {
      // cria e mostra o form...
      frmEmail Email = new frmEmail();
      Email.Show();
    
      // cria o ManualResetEvent para fechar o form quando terminar de enviar o email...
      using (ManualResetEvent resetEvent = new ManualResetEvent(false))
      {
       // pluga o SendComplete para saber quando terminou de enviar o e-mail...
       smtp.SendCompleted += new SendCompletedEventHandler(OnSmtpSendCompleted);
    
       // faz o envio assíncrono...
       smtp.SendAsync(message, resetEvent);
    
       // aguarda o término do envio...
       resetEvent.WaitOne();
      }
    
      // fecha o form...
      Email.Close();
      }
      catch (Exception ex)
      {
      MessageBox.Show(ex.Message);
      }
     }
    
     private void OnSmtpSendCompleted(object sender, AsyncCompletedEventArgs e)
     {
      // pega o ManualResetEvent para indicar para a Thread principal que o email foi enviado...
      ManualResetEvent resetEvent = (ManualResetEvent)e.UserState;
      resetEvent.Set();
    
      // verifica se deu algum erro e mostra o dialogo...
      if(e.Error != null)
      MessageBox.Show(e.Error.Message);
      else MessageBox.Show("Mensagem enviada com sucesso");
     } 
    

     

    at.,


    Rogério de Resende Ohashi | Ohashi.NET (.NET, Security, C#, WinForms, WCF, Workflow, Azure, Windows Phone, Mono)
    segunda-feira, 11 de julho de 2011 20:33
    Moderador