发送多线程SMTP电子邮件

时间:2014-11-20 16:04:01

标签: c# .net multithreading smtp

我开发了一个主要使用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,最后一行代码也有错误:   等待&#39;等待&#39;运算符只能在异步方法中使用。考虑   使用&#39; async&#39;标记此方法修饰符并改变其回报   输入&#39;任务&#39;

1 个答案:

答案 0 :(得分:0)

发生此错误是因为您在所有线程捕获的同一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);