使用参数化线程

时间:2014-01-03 10:09:31

标签: c# multithreading

我正在尝试创建一些等于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次。所以我的指数超出范围。

有谁知道为什么会这样做以及如何做到这一点?

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中更加明智。