views:

249

answers:

1

My issue is that I have a List of strings, and I want to create one thread for one string, pass the string into the thread. This is my code:

public void getImageSource(List<string> UrlLinks)
          foreach (string urlLink in UrlLinks)

            {
                ThreadStart myThread = delegate { Fetch(urlLink); };
                Thread t = new Thread(myThread);
                t.Priority = ThreadPriority.Lowest;
                t.IsBackground = true;
                t.Start();

            }

public void Fetch(string Link)
    {
        MessageBox.Show(Link);
    }

But all my messagebox return the same results, the first element in the List. How can I fix it? Thanks in advance.

+1  A: 

You're running into the captured variable issue... you're capturing the urlLink variable, not the value at the time that the delegate is created. The fix for this is to create a temporary variable inside the loop:

public void getImageSource(List<string> UrlLinks)
{
    foreach (string urlLink in UrlLinks)
    {
        string urlCopy = urlLink;
        ThreadStart myThread = delegate { Fetch(urlCopy); };
        Thread t = new Thread(myThread);
        t.Priority = ThreadPriority.Lowest;
        t.IsBackground = true;
        t.Start();
    }
}

I wouldn't expect the first URL to be fetched multiple times though - it would be more likely that the last URL would be fetched (or some variety of URLs).

See Eric Lippert's blog post on this topic for more information.

Jon Skeet
Thanks for your quick reply.I'm still a little confused about the delegate and is reading your documentation. Have a good day.P.S: Can you explain more about :"I wouldn't expect the first URL to be fetched multiple times though - it would be more likely that the last URL would be fetched (or some variety of URLs)".
Thyphuong
@Thyphuong: `Fetch` will be called with whatever the value of the variable is at the time when the delegate is actually invoked. That could well be after all the threads have been created, i.e. when the loop is completed - in which case the value would be the last one encountered. It's very non-deterministic though; in a list of "0, 1, 2, 3, 4" you could get "0, 1, 3, 4, 4" for instance.
Jon Skeet
@Jon: You are so right. I rechecked my code and found that all results returned were the last element in list. Thanks again for information you gave
Thyphuong