Простая концепция. Это для сайта, создаваемого с использованием MVC 3 и Entity Framework 4. После регистрации пользователя на сайте, на его электронный адрес отправляется письмо. Сначала я реализовал это с помощью SmtpClient.Send(), и все работало нормально. Затем мне пришла в голову светлая идея попробовать отправить письмо асинхронно. У меня возникли проблемы с двумя асинхронными подходами, которые я пробовал.
Первая реализация (из этого сообщения без ответов: 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("myaddress@gmail.com", "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);
}
}
Это работало половину времени. В другой половине я получал ошибку "Cannot access a disposed object" в CallBack.
Следующая реализация (от участника с солидной репутацией: Каковы лучшие практики использования SmtpClient, SendAsync и Dispose в .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("myaddress@gmail.com", "mypassword");
smtpClient.SendCompleted += (s, e) =>
{
smtpClient.Dispose();
message.Dispose();
};
smtpClient.SendAsync(message, null);
При такой реализации я не получаю никаких ошибок, но в режиме отладки заметно увеличивается задержка (~5 секунд) при выполнении smtpClient.SendAsync(), что наводит меня на мысль, что сообщение отправляется не асинхронно.
Вопросы:
1) что не так в первом методе, что вызывает ошибки "disposed object"?
2) есть ли проблема во второй реализации, из-за которой письмо не отправляется асинхронно? Является ли 5-секундная задержка бессмысленной?
Возможно, также важно отметить, что хотя сайт не будет поддерживать отправку большого количества электронных писем (только регистрация пользователей, рассылки по подписке и т.д.), мы ожидаем большое количество пользователей в будущем, отсюда и мое решение отправлять письма асинхронно.
Спасибо.