在ASP.NET C#中异步发送电子邮件

时间:2014-11-22 14:14:02

标签: c# asp.net email asynchronous

我想知道是否有办法在asp.net c#中异步发送电子邮件。我使用以下代码发送电子邮件:

 if (checkObavijest.Checked)
            {
                List<hsp_Kupci_Newsletter_Result> lista = ServisnaKlasa.KupciNewsletter();
                for (int i = 0; i < lista.Count; i++)
                {
                    MailMessage mail = new MailMessage();

                    mail.From = new MailAddress("*******");
                    mail.To.Add(lista[i].Email);
                    mail.Subject = "Subject";
                    mail.SubjectEncoding = Encoding.UTF8;
                    mail.BodyEncoding = Encoding.UTF8;
                    mail.IsBodyHtml = true;
                    mail.Priority = MailPriority.High;
                    mail.Body = "Some message";
                    SmtpClient smtpClient = new SmtpClient();
                    Object state = mail;
                    smtpClient.Credentials = new NetworkCredential("****@gmail.com", "****");
                    smtpClient.Port = 587;
                    smtpClient.Host = "smtp.gmail.com";
                    smtpClient.EnableSsl = true;
                    smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
                    try
                    {
                        smtpClient.SendAsync(mail, state);
                    }
                    catch (Exception ex)
                    {

                    }
                }

 void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {

            MailMessage mail = e.UserState as MailMessage;

            if (!e.Cancelled && e.Error != null)
            {
                string poruka = "Emailovi poslani!";
                ClientScript.RegisterStartupScript(this.GetType(), "myalert", "alert('" + poruka + "');", true);
            }
        }

但是当我勾选发送电子邮件的选项时,页面加载40秒,然后40秒后发送电子邮件。正如您所看到的,我现在从我的数据库中拔出20-30封电子邮件。我认为这是异步发送邮件的正确方法,但显然它不是......我如何将电子邮件发送到另一个线程,这样它不会影响使用此页面的用户?有人可以帮我解决这个问题吗?谢谢!

2 个答案:

答案 0 :(得分:0)

原因在MSDN documentation on SmtpClient.SendAsync

上提到
  

调用SendAsync后,您必须等待电子邮件传输到   在尝试使用“发送”发送另一封电子邮件之前完成   或SendAsync。

您可以通过包装方法调用SendAsync来调用ThreadPool。这会给你一些类似“即发即忘”的场景。

这样的事情:

public void SendViaThread(System.Net.Mail.MailMessage message) {
    try {
        System.Threading.ThreadPool.QueueUserWorkItem(SendViaAsync, message);
    } catch (Exception ex) {
        throw;
    }
}

private void SendViaAsync(object stateObject) {
    System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient();
    System.Net.Mail.MmailMessage message = (MmailMessage)stateObject;
    ...
    smtp.Credentials = new NetworkCredential("...");
    smtp.Port = 587;
    smtp.Host = "...";
    ...
    smtp.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
    ...
    smtp.Send(message);
}

您可以在代码中调用SendViaThread(mail)。所以,你的循环现在变成:

for (int i = 0; i < lista.Count; i++) {
    MailMessage mail = new MailMessage();
    mail.From = new MailAddress("...");
    mail.To.Add(lista[i].Email);
    mail.Subject = "...";
    ...
    mail.Body = "...";
    SendViaThread(mail);
 }

答案 1 :(得分:0)

如果您不想让主线程等待,请尝试在任务中抛出它。

Task.Factory.StartNew( () => {
  // do mail stuff here
});

请注意,尽管每次生成任务时,它都会生成一个新的(或重用)线程,而这个线程是您的系统所做的。如果您发送了30封电子邮件,则可能会触发批次线程(系统也有可编程上限)。 Task.Factory.StartNew是一种执行即发即弃过程的非常简单的方法。

http://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx (在这个例子中,代码也保留了Tasks的集合,如果你想管理它们,这很好 - 但实际上,如果你想要发射,你只需要Task.Factory.StartNew(()=>{位 - 要小心,因为你不想让孤立的线程盯住你的内存使用。