Asp.net-Mvc-3

SmtpClient.SendAsync 阻止我的 ASP.NET MVC 請求

  • August 4, 2011

我有一個發送簡單電子郵件的操作:

   [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將在完成請求之前自動等待任何未完成的非同步工作完成。這是為了確保如果您的非同步操作嘗試與HttpContextHttpResponse等進行互動,它仍然會存在。

如果你想做真正的火災並忘記,你需要將你的電話包裝在ThreadPool.QueueUserWorkItem. 這將迫使它在一個新的執行緒池執行緒上執行而無需經過SynchronizationContext,因此請求將愉快地返回。

但是請注意,如果由於任何原因應用程序域在您的發送仍在進行時關閉(例如,如果您更改了 web.config 文件、將新文件放入 bin、應用程序池回收等),您的非同步發送會突然中斷。如果您關心這一點,請查看 Phil Haacks WebBackgrounder for ASP.NET,它可以讓您排隊並執行後台工作(如發送電子郵件),以確保在應用程序域關閉的情況下正常完成.

引用自:https://stackoverflow.com/questions/6935427