2

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);
        }
    }
4
  • Which version of .Net are you using? Commented Jul 24, 2010 at 13:51
  • Do you mean that for each mail message body, the value of the string appears twice? i.e. "11", "22", "33" etc. in the body? Commented Jul 24, 2010 at 13:55
  • 2
    What happens when you replace your foreach loop with just liste.AsParallel().ForAll(SendMail);? Commented Jul 24, 2010 at 13:57
  • @Peter: no I mean that I receive mails with the same message header and body, e.g. header of first received mail: 1, header of second received mail: 1. @Nick: yes that works. but why am is this happening? Commented Jul 24, 2010 at 14:01

1 Answer 1

4

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().

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.