【问题标题】:Problem sending mails with multiple threads使用多个线程发送邮件时出现问题
【发布时间】:2011-03-20 12:20:52
【问题描述】:

我对下面的代码有疑问。邮件以重复的字符串 s 内容发送。为什么会这样?

static void Main(string[] args)
    {
        List<String> liste = new List<String>();
        liste.Add("1");
        liste.Add("2");
        liste.Add("3");
        liste.Add("4");
        liste.Add("5");
        liste.Add("6");

        foreach(string s in liste)
            new Thread(x => SendMail(s)).Start();
    }

    static void SendMail(string s)
    {
        MailMessage mailMsg = new MailMessage("from", "to");
        mailMsg.Body = s;
        mailMsg.Subject = s;

        SmtpClient smtpClient = new SmtpClient("mySMTP");

        smtpClient.UseDefaultCredentials = false;

        smtpClient.Credentials = new NetworkCredential("myUse", "myPass");
        smtpClient.EnableSsl = true;

        try
        {
            smtpClient.Send(mailMsg);
        }
        catch (SmtpException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

【问题讨论】:

  • 您使用的是哪个版本的 .Net?
  • 你的意思是对于每一个邮件正文,字符串的值出现两次?即体内的“11”、“22”、“33”等?
  • 只用liste.AsParallel().ForAll(SendMail); 替换foreach 循环会发生什么?
  • @Peter:不,我的意思是我收到的邮件具有相同的邮件标题和正文,例如第一次收到的邮件的标题:1,第二次收到的邮件的标题:1。@Nick:是的,有效。但是为什么会这样呢?

标签: c# .net multithreading smtp


【解决方案1】:

由于您使用的是 .Net 4.0,您可以在此处使用一些可用的新结构,您可以替换它:

foreach(string s in liste)
  new Thread(x => SendMail(s)).Start();

Parallel.ForEach:

Parallel.ForEach(liste, SendMail);

或者,不适合这种情况,但可以使用 .ForAll() 扩展:

liste.AsParallel().ForAll(SendMail);

有人在这里纠正我,但我 认为 正在发生的事情是,如果线程需要 任何 时间来启动,它会引用来自 foreach 的 s不属于它。将s 的值传递给SendMain 的线程,但是当它准备好时它正在获取该值......并且可能在foreach 之后循环已经继续,这意味着s指向的字符串已经改变了。

例如:如果 2 个线程启动,一个慢一个快...第一个慢的线程可能会从后面的 foreach() 迭代中获得 s,而较快的线程可能会获得正确的 s电流回路。这意味着 2 个线程获得了 相同 s 引用,而第一个线程复制了错误的值以传递给 SendMail()

【讨论】:

    猜你喜欢
    • 2010-11-10
    • 2011-03-28
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多