簡単な電子メールを送信するアクションがあります:
[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 キーを押すまで、クライアントは読み込み状態のままになります。
ベストアンサー1
これは設計によるものです。詳しくはこちら非同期処理が基盤となる非同期処理を呼び出す方法で開始された場合、リクエストを完了する前に、未処理の非同期処理が終了するまで自動的に待機します。同期コンテキストこれは、非同期操作がHTTPコンテキスト、HTTPレスポンスなど、それはまだ存在するでしょう。
本当のファイアアンドフォーゲットをしたい場合は、呼び出しを で囲む必要がありますThreadPool.QueueUserWorkItem
。これにより、同期コンテキストなので、リクエストは問題なく返されます。
ただし、送信中に何らかの理由でアプリドメインがダウンした場合(たとえば、web.config ファイルを変更した場合、新しいファイルを bin にドロップした場合、アプリプールがリサイクルされた場合など)、非同期送信は突然中断されることに注意してください。この点が気になる場合は、Phil Haacks を参照してください。Webバックグラウンダーのために詳しくはこちらこれにより、アプリ ドメインがシャットダウンした場合でも正常に終了するように、バックグラウンド作業 (電子メールの送信など) をキューに入れて実行できるようになります。