发送多封异步电子邮件

时间:2016-03-12 08:22:25

标签: c# asp.net-mvc asynchronous async-await

我想异步发送多封电子邮件。电子邮件发送后,电子邮件不会相互依赖,也不会运行任何代码,因此我想解雇多个并忘记。我正在关注this article发送异步电子邮件,但我不确定我是否正在发送多封电子邮件。

我的一些担忧;

  • 发送第二封电子邮件不应等待第一封电子邮件。
  • 我应该为每个电子邮件发送任务使用QueueBackgroundWorkItem还是使用一个QueueBackgroundWorkItem?
public class MyController : Controller
{
    public async Task SendEmailAsync(IdentityMessage message)
    {
        var mailMessage = new MailMessage
            ("abc@domain.com", message.Destination, message.Subject, message.Body);
        using(var client = new SmtpClient())
        {
            await client.SendMailAsync(mailMessage);
        }
    }

    public ActionResult Create()
    {
        Action<CancellationToken> workItem = SendEmails;
        HostingEnvironment.QueueBackgroundWorkItem(workItem);

        return View();
    }

    private async void SendEmails(CancellationToken cancellationToken)
    {
        await SendEmailAsync(new IdentityMessage(...));
        await SendEmailAsync(new IdentityMessage(...));
   }
}

1 个答案:

答案 0 :(得分:1)

在SendEmails中,每个下一封电子邮件都在等待之前的完成,您应该像这样重写:

private async Task SendEmails(CancellationToken cancellationToken)
{
        await Task.WhenAll(SendEmailAsync(new IdentityMessage(...)),
                           SendEmailAsync(new IdentityMessage(...)));
}

通过这样做,所有电子邮件将并行发送。 你也不应该在Create中使用QueueBackgroundWorkItem。你可以做下一个:

 public async Task<ActionResult> Create()
 {
        HostingEnvironment.QueueBackgroundWorkItem(async (token)=> await SendEmails() );

        return View();
 }

但请记住,如果SendEmails发生任何异常,您将不会收到有关此事件的通知。如果这对您来说可能是一个问题,请告诉我,所以我会为此提供解决方案。

但我更喜欢从网络应用程序发送电子邮件的另一种方法。它更复杂但更可靠。 Web应用程序永远不应该向smtp服务器发送消息,而是将请求存储到队列或数据库。比我们有后台应用程序监听队列,每次检测到新请求时,它尝试将其发送到smtp。如果尝试失败,系统会将请求返回队列,稍后会再尝试几次。如果您的应用程序托管在azure中,此后台应用程序可能是webjob的Windows服务。 这种方法的优点:

  1. 没有UI线程阻塞 - 将某些东西放入队列是短暂的运行操作
  2. 即使smtp服务器在一段时间内无法访问,您也确定会发送所有电子邮件
  3. 缺点:

    1. 您必须维护系统的其他组件