5

可能重复:
C# 循环中捕获的变量

我正在研究一些简单的线程应用程序,但我似乎无法让它工作:

class ThreadTest
{
    static Queue<Thread> threadQueue = new Queue<Thread>();

    static void Main()
    {
        //Create and enqueue threads
        for (int x = 0; x < 2; x++)
        {
            threadQueue.Enqueue(new Thread(() => WriteNumber(x)));
        }

        while(threadQueue.Count != 0)
        {
            Thread temp = threadQueue.Dequeue();
            temp.Start();
        }

        Console.Read();
    }

    static void WriteNumber(int number)
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(number);
        }
    }
}

目标基本上是将线程一个一个地添加到队列中,然后一个一个地通过队列并弹出一个线程并执行它。因为我的 for 循环中有“x<2”,所以它应该只创建两个线程 - 一个运行 WriteNumber(0),一个运行 WriteNumber(1),这意味着我应该以 1000 个 0 和1000 1 在我的屏幕上以不同的顺序显示,具体取决于线程的最终执行方式。

我最终得到的是2000 2。我想出的两个可能的解决方案是:我错过了一些非常明显的事情,或者将变量 x 发送到 WriteNumber 函数正在执行传递引用而不是传递值,所以当线程执行他们使用最新版本的 x 而不是设置函数时的版本。但是,据我了解,变量在 C# 中默认按值传递,并且只有在参数中包含“ref”时才通过引用传递。

4

2 回答 2

18

您正在捕获xlambda 表达式。x在启动线程之前,值会更改为 2。您需要在循环中复制value

for (int x = 0; x < 2; x++)
{
    int copy = x;
    threadQueue.Enqueue(new Thread(() => WriteNumber(copy)));
}

Lambda 表达式捕获变量。即使传递给的值WriteNumber 按值传递的,但在线程启动之前根本不会调用它——此时时间x为 2。

通过在循环中进行复制,循环的每次迭代都会获得自己单独的copy变量“实例”,并且不会改变值......所以在WriteNumber调用时,每个变量仍然具有copy相同的值x对于那个迭代。

于 2012-06-19T21:34:38.573 回答
9

发生这种情况是因为在循环完成x访问了 的值,到那时它是.2

您需要使用临时变量来防止变量捕获。

for (int x = 0; x < 2; x++)
{
    int tmp = x;
    threadQueue.Enqueue(new Thread(() => WriteNumber(tmp)));
}
于 2012-06-19T21:35:49.040 回答