我需要向我的网站用户异步发送大约5000封电子邮件作为时事通讯..问题是我不知道以异步方式发送它们的最佳方式..请帮我更新我的代码以使其异步
我的代码:
public string SendEmail()
{
foreach (var emailAddress in EmailList)
{
var message = new MailMessage("myemail@gmail.com", emailAddress);
message.Subject = "hi";
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.Credentials = new NetworkCredential("myemail@gmail.com", "*****");
client.EnableSsl = true;
client.Send(message);
}
return "done";
}
谢谢你,露西
答案 0 :(得分:2)
查看async
和await
个关键字。
https://msdn.microsoft.com/en-us/library/mt674882.aspx
C#中的async和await关键字是异步编程的核心。通过使用这两个关键字,您可以使用.NET Framework或Windows运行时中的资源创建异步方法,就像创建同步方法一样简单。使用async和await定义的异步方法称为异步方法。
MSDN解释了事物的语法方面。更大的问题是错误处理和可靠性。将5,000封电子邮件转储到列表中并点击"发送"对他们的按钮有点乐观。这些电子邮件是否需要可靠地传递?如果其中3,000个发送会发生什么,并且网络错误突然导致临时连接丢失到外发邮件服务器?当你再次开始工作时,你会重新发送所有5,000个吗?忘掉最后的2000?接收者是否会因为重复而感到生气,或者根本没有收到消息?你打算怎么解决错误?
我发现的一种模式非常有效(无论是同步发送还是异步发送),是生成消息并将每个消息存储在数据库表中,然后使用如下内容:
public void SendAllEmails()
{
var emails = SomeClass.GetAllUnsentEmails();
foreach(Email message in Emails)
{
var success = SendEmail(message);
if (!success)
{
// Do you want to do something if it fails?
}
}
}
public bool SendEmail(Email message)
{
try
{
// 1. Send the email message
// 2. Update the "SentOn" date in the database
// 3. return true
}
catch(Exception ex)
{
SomeClass.CreateEmailErrorEntry(message, ex); // store error in a table or log
return false;
}
}
答案 1 :(得分:0)
编辑:如果在操作中使用它,则应将操作标记为异步
public async Task<ActionResult> MyAction()
首先,不要为每条消息创建SmtpClient
,如下所示
而且,这应该异步发送邮件,但等待所有邮件发送
public string SendEmail()
{
var tasks = new List<Task>();
var client = new SmtpClient("smtp.gmail.com", 587);
client.Credentials = new NetworkCredential("myemail@gmail.com", "*****");
client.EnableSsl = true;
foreach (var emailAddress in EmailList)
{
var message = new MailMessage("myemail@gmail.com", emailAddress);
message.Subject = "hi";
tasks.Add(client.SendMailAsync(message));
}
while(tasks.Count > 0)
{
var idx = Task.WaitAny(tasks.ToArray());
tasks.RemoveAt(idx);
}
return "done";
}