SmtpClient.SendAsync 阻止我的 ASP.NET MVC 請求
我有一個發送簡單電子郵件的操作:
[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); }和電子郵件服務:
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) { } }當我發送電子郵件時,我使用的是 Async 方法,然後我的方法 SendAsync 立即返回,然後呼叫 RedirectToAction。但是在 client_SendCompleted 完成之前,ASP.NET 不會發送響應(在這種情況下是重定向)。
這是我想要理解的:
在 Visual Studio 調試器中查看執行時,SendAsync 立即返回(並呼叫 RedirectToAction),但在發送電子郵件之前瀏覽器中什麼都沒有發生?
如果我在 client_SendCompleted 中放置一個斷點,則客戶端將保持載入狀態……直到我在調試器中按 F5。
這是設計使然。如果非同步工作以呼叫底層SynchronizationContext的方式啟動, ASP.NET將在完成請求之前自動等待任何未完成的非同步工作完成。這是為了確保如果您的非同步操作嘗試與HttpContext、HttpResponse等進行互動,它仍然會存在。
如果你想做真正的火災並忘記,你需要將你的電話包裝在
ThreadPool.QueueUserWorkItem. 這將迫使它在一個新的執行緒池執行緒上執行而無需經過SynchronizationContext,因此請求將愉快地返回。但是請注意,如果由於任何原因應用程序域在您的發送仍在進行時關閉(例如,如果您更改了 web.config 文件、將新文件放入 bin、應用程序池回收等),您的非同步發送會突然中斷。如果您關心這一點,請查看 Phil Haacks WebBackgrounder for ASP.NET,它可以讓您排隊並執行後台工作(如發送電子郵件),以確保在應用程序域關閉的情況下正常完成.