在foreach循环中启动一个新线程

Kri*_*per 22 .net c# foreach multithreading

我有一个对象列表,我想循环遍历该列表并启动一个新线程,传入当前对象.

我写了一个我认为应该做的事情的例子,但它不起作用.具体来说,似乎线程在每次迭代时都会被覆盖.这对我来说真的没有意义,因为我每次都在创建一个新的Thread对象.

这是我写的测试代码

class Program
{
    static void Main(string[] args)
    {
        TestClass t = new TestClass();
        t.ThreadingMethod();
    }
}

class TestClass
{
    public void ThreadingMethod()
    {
        var myList = new List<MyClass> { new MyClass("test1"), new MyClass("test2") };

        foreach(MyClass myObj in myList)
        {
            Thread myThread = new Thread(() => this.MyMethod(myObj));
            myThread.Start();
        }
    }

    public void MyMethod(MyClass myObj) { Console.WriteLine(myObj.prop1); }
}

class MyClass
{
    public string prop1 { get; set; }

    public MyClass(string input) { this.prop1 = input; }
}
Run Code Online (Sandbox Code Playgroud)

我机器上的输出是

test2
test2
Run Code Online (Sandbox Code Playgroud)

但我期待它

test1
test2
Run Code Online (Sandbox Code Playgroud)

我尝试将线程更改为

ThreadPool.QueueUserWorkItem(x => this.MyMethod(myObj));
Run Code Online (Sandbox Code Playgroud)

但没有一个线程开始.

我想我只是对线程如何工作有误解.有人能指出我正确的方向,并告诉我我做错了什么?

Ree*_*sey 43

这是因为您正在关闭错误范围内的变量.这里的解决方案是在foreach循环中使用临时:

    foreach(MyClass myObj in myList)
    {
        MyClass tmp = myObj; // Make temporary
        Thread myThread = new Thread(() => this.MyMethod(tmp));
        myThread.Start();
    }
Run Code Online (Sandbox Code Playgroud)

有关详细信息,我建议阅读Eric Lippert关于这个确切主题的帖子:关闭循环变量被视为有害

  • @ root45:不要太开心.这包括每个人,包括我自己.多年来我多次写过同样的错误. (4认同)
  • 那是一个快速的反应。哇。 (2认同)