我想知道是否有办法在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封电子邮件。我认为这是异步发送邮件的正确方法,但显然它不是......我如何将电子邮件发送到另一个线程,这样它不会影响使用此页面的用户?有人可以帮我解决这个问题吗?谢谢!
答案 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(()=>{
位 - 要小心,因为你不想让孤立的线程盯住你的内存使用。