2011-11-29 10 views
8

Cada vez que llamo al smtpClient.SendAsync(...) desde mi aplicación ASP.NET MVC, las solicitudes asíncronas se cancelan automáticamente, aunque SendAsyncCancel() nunca se invoca.SmtpClient.SendAsync Las llamadas se cancelan automáticamente

Sincrónico.Send(...) solicitudes, por otro lado, pasan bien.

Mi contenedor de servicio EmailService se encarga de enviar correo electrónico asíncrono con SmtpClient desde mi aplicación ASP.NET MVC 3. Una instancia de servicio es inyectada en cada controlador MVC por StructureMap, que envuelve una nueva instancia SmtpClient en una declaración using (...) { }.

Aquí es mi método EmailService.SendAsync envoltura para SmtpClient:

public void SendAsync(EmailMessage message) 
{ 
    try 
    { 
     using (var smtpClient = new SmtpClient(_cfg.Host, _cfg.Port) 
     { 
      EnableSsl = _cfg.EnableSsl, 
      Credentials = _credentials 
     }) 
     { 
      smtpClient.SendCompleted += new SendCompletedEventHandler(Email_OnCompleted); 

      var mailMessage = new MailMessage(message.From, message.To) 
           { 
            Subject = message.Subject, 
            Body = message.Body 
           }; 

      smtpClient.SendAsync(mailMessage, message); 

      _logger.Info(string.Format("Sending async email to {0} with subject [{1}]", message.To, message.Subject)); 
     } 
    } 
    catch (Exception ex) 
    { 
     _logger.Error("Async email error: " + ex); 
     throw; 
    } 

} 

Aquí está mi Email_OnCompleted delegado:

public void Email_OnCompleted(object sender, AsyncCompletedEventArgs e) 
{ 
    var mail = (EmailMessage)e.UserState; 

    if (e.Error != null) 
    { 
     _logger.Error(string.Format("Error sending email to {0} with subject [{1}]: {2}", mail.To, mail.Subject, e.Error)); 
    } 
    else if (e.Cancelled) 
    { 
     _logger.Warn(string.Format("Cancelled email to {0} with subject [{1}].", mail.To, mail.Subject)); 
    } 
    else 
    { 
     _logger.Info(string.Format("Sent email to {0} with subject [{1}].", mail.To, mail.Subject)); 
    } 
} 

¿Por qué mensajes de correo electrónico asincrónicos siendo cancelados, pero los correos electrónicos sincrónicos pasan a través de bien? ¿Podría ser un problema de disposición?

Respuesta

12

Definitivamente puede ser un problema de eliminación. Cuando desecha el cliente, cancela cualquier operación asíncrona pendiente.

Debe deshacerse del cliente en Email_OnCompleted.

Un SO publicar en dónde puede deshacerse: Dispose SmtpClient in SendComplete?

+2

fantástico! Arranqué la instrucción using (...) y el envío asíncrono ahora funciona perfectamente. Gracias, Anders! –

+0

¿Es posible que el controlador se elimine junto con _logger antes de que se complete el envío asincrónico, dando como resultado una excepción de referencia nula en la instancia de ILogger? –

+1

Más exactamente ... "Cuando desecha el cliente, cancela cualquier operación asíncrona pendiente". = Cuando deseche SmtpClient, cancelará cualquier operación asíncrona pendiente para la instancia de la clase. –

Cuestiones relacionadas