从循环启动一个线程并传递Loop ID

Ler*_*ins 1 c# multithreading loops

我今天刚刚开始玩线程,我遇到了一些我不理解的东西.

public void Main()
{ 
    int maxValue = 5;
    for (int ID = 0; ID < maxValue; ID++)
    {
        temp(ID);
    }
}

public void temp(int i)
{
    MessageBox.Show(i.ToString());
}
Run Code Online (Sandbox Code Playgroud)

尽管它可以正常工作,但是当我尝试为每个创建一个新线程时,它只传递maxValue.请忽略这是多么糟糕,我只是这样写作一个简单的例子.

public void Main()
{ 
    int maxValue = 5;
    for (int ID = 0; ID < maxValue; ID++)
    {
        threads.Add(new Thread(() => temp(myString, rowID)));
        threads[rowID].Start();
    }
}

public void temp(string myString, int i)
{
    string _myString = myString;

    MessageBox.Show(i.ToString());
}
Run Code Online (Sandbox Code Playgroud)

鉴于此,我有两个问题:1)为什么在传递ID的新线程上调用该方法?2)如何正确编码?

Jon*_*eet 9

问题是你只有一个ID变量,而且它被捕获了.只被变量读取当实际执行新线程的代码,这常常会后,你的主线程完成循环,留IDmaxValue.在每个循环迭代中复制一次,以便每次捕获不同的变量:

for (int ID = 0; ID < maxValue; ID++)
{
    int copy = ID;
    threads.Add(new Thread(() => temp(myString, copy)));
    threads[rowID].Start();
}
Run Code Online (Sandbox Code Playgroud)

这是闭包的常见错误.阅读我的文章,比较C#和Java闭包,了解更多信息.foreach顺便说一句,同样的事情发生了- 这更令人困惑,因为它读起来每次都有一个新的变量:

foreach (string url in urls)
{
    // Aargh, bug! Don't do this!
    new Thread(() => Fetch(url)).Start();
}
Run Code Online (Sandbox Code Playgroud)

同样,你最终只得到一个变量.您需要每个委托捕获一个单独的变量,所以再次使用副本:

foreach (string url in urls)
{
    string urlCopy = url;
    new Thread(() => Fetch(urlCopy)).Start();
}
Run Code Online (Sandbox Code Playgroud)