【问题标题】:c# MailSender and sleepc# MailSender 和睡眠
【发布时间】:2012-09-22 15:45:16
【问题描述】:

我正在编写一个通过类 SmtpClient 发送电子邮件的程序。我使用此代码:

        try
        {
            MailMessage mail = new MailMessage();
            SmtpClient SmtpServer = new SmtpClient("mailSMTP.it");

            mail.From = new MailAddress("address.it");

            mail.Subject = "oggetto";

            mail.IsBodyHtml = true;
            string htmlBody = "someHTML";

            mail.Body = htmlBody;

            SmtpServer.Port = 25;

            SmtpServer.EnableSsl = false;

            foreach (string indirizzo in indirizzi)
            {
                mail.To.Clear();
                mail.To.Add(indirizzo);
                SmtpServer.Send(mail);
                System.Threading.Thread.Sleep(3000);
            }

            MessageBox.Show("e-mail spedite!");

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

但它只有在我切断“睡眠”线时才有效。为什么?我认为在此过程中休息一下是个好主意。

【问题讨论】:

  • 我不认为在过程中休息是个好主意。
  • 有效 = 它发送所有电子邮件。此外,即使我在 foreach 行设置断点,它也“有效”。只有当我使用 sleep 函数(并且没有 breakpont)运行代码时,我才会得到一个异常。
  • @StefanoCastelli 您应该发布异常的详细信息。
  • @Mufaka 它是意大利语,但我想我可以将其翻译为“现有连接被远程主机强行关闭”

标签: c# sleep smtpclient mail-sender


【解决方案1】:

鉴于有一个例外,假设它是在调用Send,我建议不要重新使用MailMessage 对象并在循环的每次迭代中创建一个新对象。例如:

        //...
        foreach (string indirizzo in indirizzi)
        {
            string htmlBody = "someHTML";
            MailMessage mail = new MailMessage 
            {
                From = new MailAddress("address.it"),
                Subject = "oggetto",
                IsBodyHtml = true,
                Body = htmlBody,
            };

            mail.To.Clear();
            mail.To.Add(indirizzo);
            SmtpServer.Send(mail);
        }

如果“工作”是指您的MessageBox 在合理的时间内出现...那么原因是因为Sleep 阻塞了UI 线程,直到所有消息都发送完毕。例如如果您尝试发送 10 条消息,UI 将暂停 30 秒(3000 毫秒 X 10)。

【讨论】:

  • 是的,我知道,但问题不同:我正在使用包含 3 个电子邮件地址的列表测试程序。使用“睡眠”行,它只将消息发送到第一个地址,然后抛出异常。如果没有睡眠线,它会发送所有电子邮件。但我不知道为什么...
【解决方案2】:

我认为你为这个进程定义了新线程,因为如果你写 System.Threading.Thread.Sleep(3000); 意味着主线程将休眠 3000 毫秒。

所以,为这个进程创建一个嵌套线程,然后你可以停止/休眠你的线程。

【讨论】:

  • 我认为问题更多是关于不使用Sleep的方法,创建一个新线程以避免阻塞主线程并不能解决问题的根源。
【解决方案3】:

在我(和others)看来,您应该不惜一切代价尽量避免睡眠,通常情况下您最终会得到一个行为奇怪的应用程序(就像您描述的行为一样)。

我会使用一个计时器来解决这个问题,该计时器使用索引来确定下一封要发送的邮件。像这样的:

    try
    {
        MailMessage mail = new MailMessage();
        SmtpClient SmtpServer = new SmtpClient("mailSMTP.it");

        mail.From = new MailAddress("address.it");

        mail.Subject = "oggetto";

        mail.IsBodyHtml = true;
        string htmlBody = "someHTML";

        mail.Body = htmlBody;

        SmtpServer.Port = 25;

        SmtpServer.EnableSsl = false;

        var index = 0;

        var timer = new System.Threading.Timer((callbackState) =>
            {
                mail.To.Clear();
                mail.To.Add(indirizzi[index]);
                SmtpServer.Send(mail);

                index++;

                if (index < indirizzi.Count)
                  timer.Change(3000, Timeout.Infinite);
                else {
                    timer.Dispose();
                    Invoke(new Action(DisplayAllEmailsSentMessage));
                }
            }, timer, 3000, Timeout.Infinite);

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }

请注意,您必须使用 Invoke 以任何方式与 Windows 窗体交互,例如显示消息框。这是因为 Threading.Timer 回调在它自己的线程上执行。

您也可以使用 Windows.Forms.Timer,但我自己很少使用它,因为它位于 Windows.Forms 命名空间中,因此仅适用于以 Windows 窗体编写的 UI。

【讨论】:

    【解决方案4】:

    由于不活动,Smtp 服务器正在断开您的连接。这最有可能释放服务器上的资源。

    来自SmtpClient 文档:

    SmtpClient当前实例建立的连接 如果应用程序希望重用 SMTP 服务器的类 向同一个 SMTP 服务器发送多条消息。这尤其 在使用身份验证或加密时很有用 连接到 SMTP 服务器。认证过程和 建立 TLS 会话可能是昂贵的操作。要求 发送大数据时为每条消息重新建立连接 发送到同一 SMTP 服务器的电子邮件数量可能会显着 对性能的影响。

    一般来说,其他响应者说您不应该在发送之间睡觉是正确的。 Smtp 服务器应该足够强大,可以处理您可以按顺序发送给它的所有电子邮件。

    【讨论】:

    • 经过大量测试,我认为这是真正的问题:如果我设置更短的睡眠时间(例如 100 毫秒)它会发送所有电子邮件,所以我猜这个问题是由 SMTP 服务器引起的不活动。我仍在测试提出的其他解决方案(非常感谢大家!!!),我会告诉你的......
    【解决方案5】:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Mail;
    using System.Net.Mime;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    
     class MailSender
        {
            public static int CreateMessageMdp(String destination,String mdp)
            {
                try
                {
                    var client = new SmtpClient("smtp.domain.com", 587)
                    {
                        Credentials = new NetworkCredential("appgestionali@domain.com", "password"),
                        EnableSsl = true
                    };
                    DateTime localDate = DateTime.Now;
                    string body = "Suite à votre demande de mot de passe le " + localDate.ToString("F") + "\n on vous envoi votre mot de passe est :" + mdp;
                    client.Send("appgestionali@domain.com", destination, "Information", body);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(""+ ex.GetBaseException());
                    return -1;
                }
                return 0;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-17
      • 2021-05-11
      • 2023-04-05
      • 2014-07-02
      • 1970-01-01
      • 2012-12-16
      • 2012-04-07
      相关资源
      最近更新 更多