【问题标题】:Sending mail with task parallel library throws error使用任务并行库发送邮件会引发错误
【发布时间】:2014-03-20 20:47:36
【问题描述】:

代码:-

List<Task> tasks = new List<Task>();
foreach (var item in arr)//arr contains 1000+ mailids
            {
                tasks.Add(Task.Factory.StartNew(() =>
                {
                    using (MailMessage msg = new MailMessage())
                        {
                            msg=getmsg();//p-shadow code no erorr here
                            SmtpClient smtp = new SmtpClient();
                            smtp.Host = smtpServer;
                            smtp.Port = smtpPort;
                            smtp.EnableSsl = isSmtpSsl != 0 ? true : false;
                            smtp.Credentials = new NetworkCredential(smtpUName,smtpPass);
                            smtp.Timeout = int.MaxValue;
                            smtp.Send(msg);//---throws error....
                            //sql code to insert db that mail is send
                        }
                }, TaskCreationOptions.LongRunning));
            }
            Task.WaitAll(tasks.ToArray<Task>());

ERROR-“发送邮件失败。”

内部错误-“无法从传输连接中读取数据:net_io_connectionclosed。”

【问题讨论】:

  • 可能是您打开了太多与 SMTP 服务器的连接,或者访问速度太快而导致您受到限制?如果您每秒执行一次……或每五秒执行一次会发生什么?
  • 我认为SmtpClient(或服务器)不支持同时连接到同一个服务器的多个连接。想想你要求它做什么:你要求多个 SmtpClient 对象连接到 same 服务器并发送电子邮件。 SmtpClient 将重复使用与同一服务器的连接,因此您可能处于竞争状态。您是否尝试过使用SendAsync 而不是Task
  • 至少,我希望您希望使用一个 SmtpClient 对象
  • 上周我有同样的项目要做。我一到电脑就会发布一些代码。 P.S 使用并行 for 循环而不是创建多个任务。

标签: .net task-parallel-library c#-5.0


【解决方案1】:

关于异常“net_io_connectionclosed”,请查看此链接,因为它可能会为您指明连接关闭原因的正确方向。可能是身份验证问题、防火墙等。

Enabling Tracing for System.Net

请在下面找到我将在您的情况下使用的代码,而不是生成 1000 个效率不高的任务。

Sending bulk emails with Tasks Parallel.ForEach

【讨论】:

  • 感谢您的解决方案..我想问一下您如何决定 const int _clientcount=15?客户端数量取决于运行的硬件还是每台机器的 smtp 数量受 .net/iis 限制
  • 这只是为了我的环境。取决于每个环境和 SMTP 服务器的设置。它可能只允许每个 IP 5 个连接。也许使用配置设置,以便您可以根据环境进行调整。
  • @RyanGunn 您设置 SMTPCLients 我需要更改它以使其适用于不同的主机。因为我会使用不同的主机 smtp 凭据发送电子邮件。所以我必须为不同的主机启动 15 个客户端。你能举个例子告诉我怎么做吗
【解决方案2】:

正如 Jim 所提到的,您可能只是遇到了节流/拒绝的情况。恕我直言,您可能会更成功:1)使用单个 SmtpClient 而不是其中 N 个(因此单个客户端可以根据需要在内部进行序列化)和 2)使用内置异步调用(SendMailAsync)而不是 StartNew 并调用同步版本。

类似:

var messages = ... // get collection of MailMessage instances
var smtpClient = new SmtpClient { ... }; // construct a single SmtpClient
var tasks = messages.Select(smtpClient.SendMailAsync).ToArray();
Task.WaitAll(tasks);

我不确定这是否真的有很大帮助 - 如果仍然失败,您可能只需要创建一个长时间运行的任务来串行发送电子邮件。

【讨论】:

  • 如果正在进行电子邮件传输并且您再次调用 SendAsync 或 Send,您将收到 InvalidOperationException。取自“msdn.microsoft.com/en-us/library/…
  • @DNNDev.co.za - 我的代码 sn-p 调用的方法是 SendMailAsync,而不是 Send 或 SendAsync。当然,它的行为可能相同,只是文档没有更新,但那一点文档并没有说它会失败:)
  • 抱歉,我想念您的代码在做什么,并认为它正在调用 SendAsync。
猜你喜欢
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多