C#中的简单线程

Jak*_*ake 5 c# multithreading

可能重复:
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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

目标基本上是逐个向队列添加线程,然后逐个遍历队列并弹出一个线程并执行它.因为我的for循环中有"x <2",它应该只生成两个线程 - 一个运行WriteNumber(0),另一个运行WriteNumber(1),这意味着我应该以1000 0和我的屏幕上的1000 1是不同的顺序,具体取决于线程的最终执行方式.

我最终得到的是2000 2.我提出的两个可能的解决方案是:我错过了一些明显的东西,或者将变量x发送到WriteNumber函数正在执行pass-by-reference而不是pass-by-value,所以当线程执行它们使用最新版本的x而不是设置函数时的版本.但是,据我所知,变量在C#中默认按值传递,如果在参数中包含"ref",则仅通过引用传递.

Jon*_*eet 18

你正在捕获xlambda表达式.x在启动线程之前更改为2 的值.你需要做一个有价值的副本的循环:

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

Lambda表达式捕获变量.即使传递给的值WriteNumber 按值传递的,也不会在线程启动之前调用它 - 到时x为2.

通过在循环中制作副本,循环的每次迭代得到的自己单独的"实例" copy变量,而不会改变价值......这样的时候WriteNumber被调用,每个copy变量仍然有相同的值x了对于那次迭代.


Ken*_*rey 9

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

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

for (int x = 0; x < 2; x++)
{
    int tmp = x;
    threadQueue.Enqueue(new Thread(() => WriteNumber(tmp)));
}
Run Code Online (Sandbox Code Playgroud)