我正在尝试创建一些等于nOfplayers
的线程。
我是这样做的:
for (int i = 0; i < nOfPlayers; i++)
{
thr[i] = new Thread(
() => playerComm[i].Communicate(handler[i], ref game, ref table));
thr[i].Start();
}
我只有一次使用这个循环。但不知何故,我不知道为什么,new Thread
的执行时间超过nOfPlayers-1
次。所以我的指数超出范围。
有谁知道为什么会这样做以及如何做到这一点?
答案 0 :(得分:2)
不,它正在执行正确的次数 - 但是你正在捕获i
,它在线程使用它之前递增。
在循环中创建i
的副本:
for (int i = 0; i < nOfPlayers; i++)
{
int player = i;
thr[i] = new Thread(
() => playerComm[player].Communicate(handler[player], ref game, ref table));
thr[i].Start();
}
有关详细信息,请参阅Eric Lippert的"Closing over the loop variable considered harmful"博客文章。
另外,在这样的多个线程中使用ref
对我来说是错误的 - 你确定你需要ref
个参数吗?有关含义的详细信息,请参阅my article on parameter passing in C#。
最后,鉴于您在这里看起来有两个集合 - 一个用于处理程序,一个用于通信器,请考虑使用单个集合,其中集合的每个元素都知道这两个部分。
然后在C#5中你可以逃脱:
// Only correct in C# 5 and later!
var threads = new List<Thread>();
foreach (var player in players)
{
// HandleCommunications would call comm.Communicate(handler, game, table)
var thread = new Thread(() => player.HandleCommunications(game, table));
thread.Start();
threads.Add(thread);
}
请注意,在C#3和4中,你仍然需要在循环中使用额外的局部变量,但是foreach
关于变量捕获的行为在C#5中更加明智。