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

C# 在ASP.NET C中异步发送电子邮件#,c#,asp.net,email,asynchronous,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++)

我想知道是否有一种方法可以在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);
            }
        }
if(选中obavijest.Checked)
{
List lista=ServisnaKlasa.KupciNewsletter();
for(int i=0;i

但是,当我选择发送电子邮件时,页面加载时间大约为40秒,然后在40秒后发送电子邮件。正如你所看到的,我正在从数据库中取出20-30封电子邮件。我认为这是异步发送邮件的正确方法,但显然不是……我如何将电子邮件发送推送到另一个线程呢esn不会影响正在使用此页面的用户吗?有人能帮我解决吗?谢谢!

原因在下面的

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

您可以使用
ThreadPool
通过包装的方法调用
SendAsync
。这会给您带来类似于火灾和遗忘场景的效果

大概是这样的:

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);
 }
for(int i=0;i
如果不想让主线程等待,请尝试在任务中丢弃它

Task.Factory.StartNew( () => {
  // do mail stuff here
});
请注意,尽管每次生成任务时,都会生成一个新的(或重复使用)系统已生成的线程。如果要发送30封电子邮件,则可能会发送很多线程(系统也有一个可编程的cap)。
task.Factory.StartNew
是执行“先发后忘”过程的一种非常简单的方法


(在本例中,代码还保留了一组
任务
,如果您愿意管理它们,这很好——但实际上,您只需要
Task.Factory.StartNew(()=>{
bit,如果您想启动并忘记。请小心,因为您不想让孤立线程与内存使用率挂钩。

我会尝试一下,但为什么您要将sendviathread函数声明为bool,为什么不作废?哦..这是我的一个项目中代码的一部分..我正在做更多的工作并返回bool以指示问题。您我真的不需要。谢谢你指出,我将删除该部分。你能更具体地说明我如何将其构建到我现有的代码中吗?我不太确定我应该在这里做什么…@perkes456:我已经让答案更清楚了。你所要做的就是删除现有循环中的
smtpclient
相关代码,然后调用
SendViaThread(mail)
而不是
smtpClient.SendAsync(mail,state)
我应该这样做:对象状态=mail;试试{SendViaAsync(state);SendViaThread(mail);}还是试试{SendViaThread(mail);}哪一个?有没有什么方法可以在这些线程发送完邮件后处理它们…不是真的,你可以让系统处理释放这些任务。一旦它们完成,它们就完成了。--请看以下内容:作为旁白,你也可以使用Task.Run(而不是.StartNew)--也要注意这一点。如果您想了解跟踪任务的情况,可以将它们添加到所列示例中的集合中,或者在启动时使用
将它们包装在
中(使用清理自身及其局部).但我建议只让.NET处理清理,而不要为此烦恼。过去,我在集合中添加了衍生线程,这样我就可以监视它们的进程、它们在做什么,并能够在需要时删除它们(多线程是一个有趣的[不是]世界).Task.Run/StartNew使您不必太担心线程状态、竞态条件等,就可以轻松地解决问题。这非常适合您的fire and forget场景。使用问题中发布的第一个代码,我遇到了一个“内存不足”的错误,这可能是错误的原因吗?