简体   繁体   中英

Issue with multithreading and for loop counter in C#

I am currently building a game using the Unity engine and C# in which i generate a gameworld. Currently it exists of a byte[,] of predetermined size, (between 512 and 4096, so for a total size of 4096x4096=16,7 million tiles). While implementing a multithreaded variant of a method which fills my array randomly with a 1 or a 2 dependent on a randomgenerator, i stumbled across a very weird problem.

Here is my code:

void CellularAutomata()
    {
        int ThreadCount = Environment.ProcessorCount; //Amount of cores. 4 in my case
        ThreadCount *= 4; // Multiplying by 4 to get higher amount of threads.
        int ThreadWorkSizeX = WorldProps.Size.x / ThreadCount; //Divide map x size by threadcount
        int ThreadWorkSizeY = WorldProps.Size.y / ThreadCount; // same for y
        Thread[] Threads = new Thread[ThreadCount]; //create simple array
        //Main thread nog mee laten werken
        for (int i = 0; i < ThreadCount; i++) //for loop to create threads
        {
            UnityEngine.Debug.Log(i); // 0
            Threads[i] = new Thread(() => {
                UnityEngine.Debug.Log("Thread says " + (i)); // i is 1???
                //Doing i-1 to correct this, but give unpredictable results.
                for (int x = ( (i-1) * ThreadWorkSizeX); x < (( (i-1) * ThreadWorkSizeX) + ThreadWorkSizeX); x++)
                {
                    for (int y = ( (i-1) * ThreadWorkSizeY); y < (( (i-1) * ThreadWorkSizeY) + ThreadWorkSizeY); y++)
                    {
                        if (WorldProps.RandomGen.Next(0, 100) < CellProps.FillPercentage)
                        {
                            TileTypeXZ[x, y] = 2;
                        }
                        else
                        {
                            TileTypeXZ[x, y] = 1;
                        }
                    }
                }
            });
            //Inserting a debug.log here affects the results?
            Threads[i].Start();
        }

        //Joining up again with my threads.
        //(Yes i know, main thread not really doing anything yet, but i want this working first.)
        for (int p = 0; p < ThreadCount; p++)
        {
            Threads[p].Join();
        }

    }

All this is done in this simple method. It currently obviously does not fully implement a Cellular Automata algorithm yet, but it has to in the future. I first wanted to get multithreaded random filling my map working. This whole process is fully contained in this method, and there are no external variables capable of affecting this method except my WorldProps object, which only houses a couple variables related to the size of the world and such. These ain't the problem here.

Therefore i wanted to split up my world, which is a two-dimensional array of bytes, and assign each thread a part of my world to fill. Here, however, i am stumbling upon some serious problems. First i also tried to manually start each thread after the for loop, but this resulted in i always being equal to the amount of threads (16 in my case), so this was a no go, but now there is this weird issue when i create a new Thread object, suddenly my 'i' variable is being incremented by one. Correcting this by using (i-1) does give me some results, if i modify the for loop, (so ignore the i-1 for now) but it stops working when using more than a single thread.

For some reason placing a Debug.Log ("Something"); on the specified line affects the results my threads are creating.

Sorry for my poor English, i don't yet master the language since i am just 17.

Either way,

Has anyone here any clue why i am having these weird problems with this for loop counter? Many thanks,

All threads share the same reference to i . Use a temporary variable

This is your problematic code

for(int i=0; i < 10; i++)
{
    new Thread(() => {
        Console.WriteLine(i);
    })
    .Start();
}

Change it to:

for(int i=0; i < 10; i++)
{
    var j = i;
    new Thread(() => {
        Console.WriteLine(j);
    })
    .Start();
}

For more info about closures : http://www.codethinked.com/c-closures-explained

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM