Prosta koncepcja tutaj. Dotyczy to witryny budowanej przy użyciu MVC 3 i Entity Framework 4. Po zarejestrowaniu użytkownika w serwisie, na jego adres e-mail wysyłana jest wiadomość e-mail. Po raz pierwszy zaimplementowałem to za pomocą SmtpClient.Send() i działało dobrze. Potem wpadłem na pomysł, aby spróbować asynchronicznie wysłać wiadomość e-mail. Mam problemy z dwoma podejściami asynchronicznymi, których próbowałem.Dwa sposoby wysyłania wiadomości e-mail przez SmtpClient asynchronicznie, różne wyniki
Pierwsza implementacja (z tego postu bez odpowiedzi: 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);
}
}
To działało przez połowę czasu. W drugiej połowie dostanę błąd "Nie można uzyskać dostępu do obiektu" w CallBack.
Następny realizacja (od członka z solidnej reputacji: 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);
Dzięki tej implementacji ja nie otrzymuję żadnych błędów, ale jest zauważalnie dłużej opóźnienie (~ 5 sekund) w trybie debugowania podczas smtpclient. Wykonywana jest funkcja SendAsync(), co pozwala mi sądzić, że nie jest ona wysyłana asynchronicznie.
Pytania:
1), co jest złego w pierwszej metodzie, która jest przyczyną błędów „zbyte obiekt”?
2) czy druga implementacja ma problem powodujący, że wiadomość e-mail nie jest wysyłana asynchronicznie? Czy opóźnienie 5 sekund jest bez znaczenia?
Może być również ważne, aby pamiętać, że chociaż witryna nie musi obsługiwać wysyłania dużej liczby wiadomości e-mail (tylko rejestracja użytkownika, opcjonalne biuletyny itp.), Przewidujemy dużą liczbę użytkowników w przyszłości, stąd moja decyzja o asynchronicznym wysyłaniu e-maili.
Dzięki.
Dzięki za odpowiedź. Teraz widzę, że obiekt jest usuwany, zanim przewodnik ma szansę wystrzelić. Rozumiem również, że oba SmtpClient muszą zostać usunięte, a EndInvoke musi zostać wywołany. Czy osiąga to podejście nr 2? –