Fel*_*oto 23 email smtp smtpclient asp.net-mvc-3
我有一个发送简单电子邮件的动作:
[HttpPost, ActionName("Index")]
public ActionResult IndexPost(ContactForm contactForm)
{
if (ModelState.IsValid)
{
new EmailService().SendAsync(contactForm.Email, contactForm.Name, contactForm.Subject, contactForm.Body, true);
return RedirectToAction(MVC.Contact.Success());
}
return View(contactForm);
}
Run Code Online (Sandbox Code Playgroud)
和电子邮件服务:
public void SendAsync(string fromEmail, string fromName, string subject, string body, bool isBodyHtml)
{
MailMessage mailMessage....
....
SmtpClient client = new SmtpClient(settingRepository.SmtpAddress, settingRepository.SmtpPort);
client.EnableSsl = settingRepository.SmtpSsl;
client.Credentials = new NetworkCredential(settingRepository.SmtpUserName, settingRepository.SmtpPassword);
client.SendCompleted += client_SendCompleted;
client.SendAsync(mailMessage, Tuple.Create(client, mailMessage));
}
private void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
Tuple<SmtpClient, MailMessage> data = (Tuple<SmtpClient, MailMessage>)e.UserState;
data.Item1.Dispose();
data.Item2.Dispose();
if (e.Error != null)
{
}
}
Run Code Online (Sandbox Code Playgroud)
当我发送电子邮件时,我使用的是Async方法,然后我的方法SendAsync立即返回,然后调用RedirectToAction.但是,在client_SendCompleted完成之前,ASP.NET不会发送响应(在这种情况下是重定向).
这是我想要了解的内容:
在Visual Studio调试器中观察执行时,SendAsync立即返回(并调用RedirectToAction),但在发送电子邮件之前,浏览器中没有任何反应?
如果我在client_SendCompleted中放置一个断点,客户端将继续加载....直到我在调试器中点击F5.
Dam*_*rds 27
这是设计的.如果异步工作以调用底层SynchronizationContext的方式启动,ASP.NET将在完成请求之前自动等待任何未完成的异步工作完成.这是为了确保如果您的异步操作尝试与HttpContext,HttpResponse等进行交互,它仍将存在.
如果你想做真假和忘记,你需要打电话ThreadPool.QueueUserWorkItem
.这将强制它在新的线程池线程上运行而无需通过SynchronizationContext,因此请求将很高兴地返回.
但是请注意,如果出于任何原因,当您的发送仍在进行时,应用程序域将停止运行(例如,如果您更改了web.config文件,将新文件放入bin,应用程序池已回收,等等)您的异步发送会突然中断.如果您关心这一点,请查看用于ASP.NET的 Phil Haacks WebBackgrounder,让您排队并运行后台工作(如发送电子邮件),以确保在app域关闭的情况下优雅地完成.
这是一个有趣的.我重现了意想不到的行为,但我无法解释.我会继续挖掘.
无论如何,解决方案似乎是将后台线程排队,这种方式在使用中失败了SendAsync
.你最终得到这个:
MailMessage mailMessage = new MailMessage(...);
SmtpClient client = new SmtpClient(...);
client.SendCompleted += (s, e) =>
{
client.Dispose();
mailMessage.Dispose();
};
ThreadPool.QueueUserWorkItem(o =>
client.SendAsync(mailMessage, Tuple.Create(client, mailMessage)));
Run Code Online (Sandbox Code Playgroud)
哪个可能成为:
ThreadPool.QueueUserWorkItem(o => {
using (SmtpClient client = new SmtpClient(...))
{
using (MailMessage mailMessage = new MailMessage(...))
{
client.Send(mailMessage, Tuple.Create(client, mailMessage));
}
}
});
Run Code Online (Sandbox Code Playgroud)