我正在尝试学习如何在C#中使用多线程。我在this tutorial工作,它解释了使用lambda表达式传递参数。我制作了一个玩具程序来测试这个,但我对输出感到困惑。
这是我的代码:
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread(int id)
{
Console.WriteLine(string.Format("Child thread {0} starts", id));
}
static void Main(string[] args)
{
for (int i=0; i<10; i++)
{
Console.WriteLine(string.Format("i: {0}", i));
Thread childThread = new Thread( () => CallToChildThread (i) );
childThread.Start();
}
}
}
}
这是输出:
i: 0
i: 1
Child thread 1 starts
i: 2
Child thread 2 starts
i: 3
Child thread 3 starts
i: 4
Child thread 4 starts
Child thread 5 starts
i: 5
i: 6
Child thread 6 starts
i: 7
i: 8
Child thread 7 starts
i: 9
Child thread 9 starts
Child thread 8 starts
Child thread 10 starts
子函数仅打印出传递的id的值。我预计这些范围从0到9,但CallToChildThread
代替显示1到10.有人可以解释原因吗?
答案 0 :(得分:2)
我刚刚运行该程序并得到以下结果:
i: 0
i: 1
i: 2
Child thread 2 starts
i: 3
Child thread 2 starts
Child thread 3 starts
i: 4
Child thread 4 starts
Child thread 4 starts
i: 5
i: 6
i: 7
Child thread 7 starts
Child thread 7 starts
i: 8
i: 9
Child thread 9 starts
Child thread 9 starts
Child thread 10 starts
这很好地演示了多线程的一个问题:共享变量。在这一行:
Thread childThread = new Thread( () => CallToChildThread (i) );
您将假设您创建了一个当前值为i
的lambda。你没有。您使用引用创建一个lambda到i
,即循环变量。只有当您的子线程到达CallToChildThread
的开头(可能在稍后的某个时间发生)时,才会评估i
的值并将其复制到局部变量id
。
修复很简单:
int _i = i;
Thread childThread = new Thread(() => CallToChildThread(_i));
这将产生0到9的子线程。