线程修改意外变量

时间:2013-12-10 20:23:19

标签: c# multithreading mono

我对C#线程很新,所以请提前为这个新手错误道歉。以下代码的目的是评估存储在名为members的数组中的填充的适合度。过程members.calculateFitness()是一个黑盒子(即我不能修改它以提高性能),所以我试图设置同时调用黑盒子的线程,每个线程将处理1 / THREAD_COUNT个人口成员(因此,如果THREAD_COUNT = 4,则每个线程将处理1/4的人口。)

在第一个for循环中,我初始化每个线程。在第二个for循环中,我启动了线程。

public void ThreadedPrintPopFitness ()
    {
        int THREAD_COUNT = 1;
        int membersPerThread = members.Length / THREAD_COUNT;

        Thread[] fitnessCalculator = new Thread[THREAD_COUNT];
        int[] threadResult = new int[THREAD_COUNT];

        for (int i = 0; i < THREAD_COUNT; i++) {
            int start = i * membersPerThread;
            int stop = (i+1) * membersPerThread;
            fitnessCalculator [i] = new Thread (() => getMaxFitness (members, start, stop, ref threadResult [i]));
        }

        for (int i = 0; i < THREAD_COUNT; i++) {
            fitnessCalculator [i].Start ();
        }

        for (int i = 0; i < THREAD_COUNT; i++) {
            fitnessCalculator [i].Join ();
        }

        int maxFitness = 0;
        for (int i = 0; i < THREAD_COUNT; i++) {
            if (maxFitness < threadResult [i])
                maxFitness = threadResult [i];
        }

        Console.WriteLine ("(ThreadedCount) Fittest Population Member's Fitness: " + maxFitness);
    }

    private static void getMaxFitness (PopulationMember[] members, int start, int stop, ref int result)
    {
        int maxFitness = 0;

        for (int i = start; i < stop && i < members.Length; i++) {
            if (members [i].calculateFitness () > maxFitness) {
                maxFitness = members [i].lastFitness;
            }
        }

        result = maxFitness;
    }

单步执行代码表明它进入第二个for循环,然后跳回第一个for循环并在整数i上声明一个IndexOutOfBoundsException。我可以看到i = THREAD_COUNT(我尝试过THREAD_COUNT个不同的数字)。

我完全不知所措,我做错了什么? 提前谢谢!

enter image description here

2 个答案:

答案 0 :(得分:0)

Servy发现它,我甚至记得现在在John Skeet的书中读到这个。我必须在for循环中复制i,这就解决了。

谢谢!

答案 1 :(得分:0)

如评论中所述,i被捕获,当增加时,该函数引用新值。

您应该做的是将其值复制到局部变量:

for (int i = 0; i < THREAD_COUNT; i++) {
      int start = i * membersPerThread;
      int stop = (i+1) * membersPerThread;
      int resultId = i;
      fitnessCalculator [i] = new Thread (() => getMaxFitness (members, start, stop, ref threadResult [resultId]));
}