发送背景电子邮件异步仍然冻结UI

时间:2016-11-26 14:04:43

标签: c# asp.net email asynchronous

我正在开发一个ASP.NET MVC项目。我试图在后台运行时发送电子邮件而不冻结UI。大多数文章说现在可以用.NET异步发送电子邮件来完成。我发送异步电子邮件但它仍然冻结了用户界面。我正在做的是我注册输入电子邮件和密码,然后在后台发送验证邮件。我的发送电子邮件代码如下。

我有这样的界面。

public interface IMailHelper
    {
        Task SendEmailAsync(string to, string subject, string body, bool isHtml = true);
    }

这是使用send-email方法的接口实现

public class MailHelper : IMailHelper
    {
        private string EmailAddress { get; set; }
        private string EmailPassword { get; set; }
        private int Port { get; set; }
        private string Host { get; set; }

        public MailHelper()
        {
            this.EmailAddress = AppConfig.SystemEmailAddress;
            this.EmailPassword = AppConfig.SystemEmailPassword;
            this.Port = AppConfig.SystemMailPort;
            this.Host = AppConfig.SystemMailHost;
        }

        public async Task SendEmailAsync(string to, string subject, string body, bool isHtml = true)
        {
            var mail = new MailMessage();
            mail.To.Add(to);
            mail.From = new MailAddress(this.EmailAddress);
            mail.Subject = subject;
            mail.Body = body;
            mail.IsBodyHtml = isHtml;

            using (var smtp = new SmtpClient())
            {
                var credential = new NetworkCredential
                {
                    UserName = this.EmailAddress,
                    Password = this.EmailPassword
                };
                smtp.UseDefaultCredentials = false;
                smtp.Credentials = credential;
                smtp.Host = this.Host;
                smtp.Port = this.Port;
                smtp.EnableSsl = true;
                await smtp.SendMailAsync(mail);
            }
        }
    }

正如您所看到的,我正在发送异步电子邮件。

这是我在控制器中的动作方法

    [HttpPost]
    [AllowAnonymous]
    //[AngularValidateAntiForgeryToken]
    public async Task<JsonResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            //Do other stuffs here
            await  _mailHelper.SendEmailAsync(user.Email, AppConfig.AccountVerifyMailSubject, WebHelper.BuildAccountVerificationEmailBody(user.UserName, verificationUrl));
        }
        // Do other stuffs here
    }

正如您所看到的,我正在尝试在操作方法中在后台发送电子邮件。我的代码正在成功发送邮件。但我确信它会冻结用户界面,因为它需要的时间比它应该的要长。我测试了很多次。与正常发送电子邮件没什么不同为什么它会冻结用户界面?我的代码没有在新流程中发送后台电子邮件。

1 个答案:

答案 0 :(得分:1)

  

现在大多数文章都说可以通过.NET异步发送电子邮件来完成。

那些文章都错了,抱歉。

我有一篇博文发布到various implementations of ASP.NET background tasks。总而言之,如果您不在乎电子邮件偶尔会丢失,那么您只需使用HostingEnvironment.QueueBackgroundWorkItem

[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> Register(RegisterViewModel model)
{
  if (ModelState.IsValid)
  {
    ...
    HostingEnvironment.QueueUserWorkItem(_ =>
        _mailHelper.SendEmailAsync(user.Email, AppConfig.AccountVerifyMailSubject, WebHelper.BuildAccountVerificationEmailBody(user.UserName, verificationUrl));
  }
  ...
}

如果您照顾电子邮件不会丢失,那么您必须将它们放置在某种可靠的队列(Azure队列或MSMQ)中,并且有一个独立的后台工作人员发送实际的电子邮件(Azure功能/ WebJob /辅助角色或Win32服务)。