views:

27

answers:

1

Hi

i have a problem with the code below. the mail is sent with a duplicate content of the string s. why is this happening?

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);
        }
    }
+1  A: 

Since you're using .Net 4.0 you can use a few new constructs available here, you can replace this:

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

With a Parallel.ForEach:

Parallel.ForEach(liste, SendMail);

Or, inappropriate for the case but works the .ForAll() extension:

liste.AsParallel().ForAll(SendMail);

Someone correct me here, but what I think is happening is that if a Thread takes any time to start up it's referencing a s from the foreach that doesn't belong to it. The thread it passing a the value of s into SendMain, but it's getting that value when it's ready for it...and that may be after the foreach loop has already moved on, meaning that the string that s points to has changed.

For example: If 2 threads start, one slow and one fast...the first slow one might get an s from a later foreach() iteration, and the faster one may get the correct s for the current loop. That means 2 threads got the same s reference, and the first thread copied the wrong value to pass into SendMail().

Nick Craver