在我的下面的代码中,Id
的{{1}}属性未按预期确定(ThreadClass
等)。
如果我调试并减慢ThreadArray[0]'s ThreadClass.Id = 0, ThreadArray[1]'s ThreadClass.Id = 1,
的速度,一切都按预期工作。但是当程序以全速运行时,我得到所有Thread.Start()'s
(或类似的)。我无法锁定Id's = 4
,因为它不是引用变量。显然,我遇到了竞争条件。我做错了什么?
Main.cs
i
ThreadClass.cs
for (int i = 0; i < ThreadCount; i++)
{
ThreadArray[i] = new Thread(() =>
{
new ThreadClass(i);
});
ThreadArray[i].Start();
}
预期输出:
private int Id { get; set; }
public ThreadClass(int i) {
Id = id;
while(true)
{
Console.WriteLine("I am thread " + i");
Thread.Sleep(5000);
}
}
实际输出:
I am thread 0
I am thread 1
I am thread 2
I am thread 3
... 5 second wait ...
I am thread 0
I am thread 1
I am thread 2
I am thread 3
请注意,此时I am thread 4
I am thread 4
I am thread 4
I am thread 4
... 5 second wait ...
I am thread 4
I am thread 4
I am thread 4
I am thread 4
的每个实例都会初始化为有效的ThreadArray
对象。
答案 0 :(得分:2)
您使用的是不会关闭i
变量的新副本的C#版本。在执行线程时,i
处于或接近ThreadCount
。只需创建变量的副本,以便闭包可以捕获它:
for (int i = 0; i < ThreadCount; i++)
{
int temp = i;
ThreadArray[i] = new Thread(() =>
{
new ThreadClass(temp);
});
}
顺便说一句,VS 2012(或.NET 4.5)中的C#版本修复了这个问题。见http://msdn.microsoft.com/en-us/library/hh678682(v=vs.110).aspx
答案 1 :(得分:-1)
将你的ThreadArray [i] .Start()移到for循环之外,然后在启动线程之前简单地设置所有类。即使你必须循环两次,它应该确保一切都按照你想要的顺序/状态发生。
- 编辑Darnit在我做之前得到了答案 - :)