可能重复:
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了对于那次迭代.
发生这种情况是因为在循环结束后x访问了值,到那时它是.2
您需要使用临时变量来防止变量捕获.
for (int x = 0; x < 2; x++)
{
int tmp = x;
threadQueue.Enqueue(new Thread(() => WriteNumber(tmp)));
}
Run Code Online (Sandbox Code Playgroud)