发送多线程 SMTP 电子邮件
本文关键字:电子邮件 SMTP 多线程 | 更新日期: 2023-09-27 18:31:09
我开发了一个主要使用SMTP发送电子邮件的应用程序。
MailMessage mail = new MailMessage();
mail.From = new MailAddress("from", "to");
mail.Subject = "subject";
mail.Body = "body";
SmtpClient client = new SmtpClient("my domain");
client.Credentials = new NetworkCredential(from, "MyPass");
client.Send(mail);
这工作正常,但现在我想同时发送几条消息而无需等待,所以我将所有消息都放在一个列表中:
List<MailMessage> emails = new List<MailMessage>();
emails.Add(new MailMessage (...));
emails.Add(new MailMessage (...));
emails.Add(new MailMessage (...));
...
我想打开每封电子邮件的新Thread
:
// Generate and execute all mails concurrently
var emailTasks = emails.Select(msg =>
{
client = new SmtpClient();
return client.SendAsync(msg);
});
// Asynchronously wait for all of them to complete.
await Task.WhenAll(emailTasks);
并得到此错误:
没有 SendMailAsync,并且最后一行代码也出现错误: "await"运算符只能在异步方法中使用。考虑 使用"async"修饰符标记此方法并更改其返回值 键入"任务"
发生此错误的原因是您在所有线程捕获的同一SmtpClient
实例上进行多个 SMTP 调用。
您可以在SmtpClient.Send
的源代码中看到它(为简洁起见,缩短):
try
{
// If there is already an ongoing SMTP request
if (InCall)
{
throw new InvalidOperationException(SR.GetString(SR.net_inasync));
}
}
通常,不需要使用任何线程来执行 I/O 绑定操作,因为它们本质上是异步的。
相反,您可以使用async-await
来利用异步 API:
// Generate and execute all mails concurrently
var emailTasks = emails.Select(msg =>
{
var client = new SmtpClient();
return client.SendMailAsync(msg));
});
// Asynchronously wait for all of them to complete.
await Task.WhenAll(emailTasks);