Semplice concetto qui. Questo è per un sito che viene creato utilizzando MVC 3 e Entity Framework 4. Dopo che un utente si registra sul sito, viene inviata un'email al suo indirizzo email. L'ho implementato per la prima volta utilizzando SmtpClient.Send() e ha funzionato correttamente. Poi ho avuto la brillante idea di provare a inviare l'e-mail in modo asincrono. Sto riscontrando problemi con i due approcci asincroni che ho provato.Due modi per inviare e-mail tramite SmtpClient in modo asincrono, diversi risultati
Prima implementazione (da questo post senza risposta: https://stackoverflow.com/questions/7558582/how-to-dispose-using-smtpclient-send-and-asynccallback):
public bool Emailer(){
.
.
.
using (var smtpClient = new SmtpClient())
{
smtpClient.EnableSsl = true;
smtpClient.Host = "smtp.gmail.com";
smtpClient.Port = 587;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential("[email protected]", "mypassword");
var sd = new SendEmailDelegate(smtpClient.Send);
var cb = new AsyncCallback(SendEmailResponse);
sd.BeginInvoke(message, cb, sd);
return true;
}
}
private delegate void SendEmailDelegate(System.Net.Mail.MailMessage m);
private static void SendEmailResponse(IAsyncResult ar)
{
try
{
SendEmailDelegate sd = (SendEmailDelegate)(ar.AsyncState);
sd.EndInvoke(ar); // "cannot access a disposed object" errors here
}
catch (Exception e)
{
_logger.WarnException("Error on EndInvoke.", e);
}
}
Questo ha funzionato la metà del tempo. L'altra metà otterrebbe un errore "Impossibile accedere a un oggetto disposto" nel CallBack.
implementazione successiva (da un membro con solida reputazione: What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0):
var smtpClient = new SmtpClient();
smtpClient.EnableSsl = true;
smtpClient.Host = "smtp.gmail.com";
smtpClient.Port = 587;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential("[email protected]", "mypassword");
smtpClient.SendCompleted += (s, e) =>
{
smtpClient.Dispose();
message.Dispose();
};
smtpClient.SendAsync(message, null);
Con questa implementazione non ottengo eventuali errori, ma c'è un ritardo notevolmente più lungo (~ 5 secondi) in modalità debug quando SMTPClient. SendAsync() viene eseguito, portandomi a pensare che non venga inviato in modo asincrono.
Domande:
1) cosa c'è di sbagliato nel primo metodo che sta causando gli errori "oggetto eliminato"?
2) la seconda implementazione ha un problema che causa il mancato invio dell'email in modo asincrono? Il ritardo di 5 secondi è privo di significato?
Potrebbe anche essere importante notare che, sebbene il sito non debba supportare l'invio di un gran numero di e-mail (solo registrazione utente, newsletter opt-in, ecc.), Prevediamo un numero elevato di utenti in futuro, da qui la mia decisione di inviare e-mail in modo asincrono.
Grazie.
Grazie per la risposta. Ora vedo che l'oggetto è disposto prima che il gestore abbia la possibilità di sparare. Inoltre, comprendo che entrambi SmtpClient devono essere eliminati e EndInvoke deve essere chiamato. L'approccio n. 2 porta a termine questo? –