0

I have some issues with an application I'm coding. It's job is to solve a maze using threads. One thread begins, and for each bifurcation it calls a static method in another class, passing parameters that the other thread needs, and then starts threads for each path. My outputs are all messed up, and I'm not sure if it's a Multithreading problem or maybe a problem with the references. Here's some of the code (Each thread is given a new instance of an Explorer class):

This is the Run() method for each thread:

public void Explore()
{
    while (ImDone == false)
    {
        Move();
        if (ActualPosition[0] != Labyrinth.ExitPoint[0] || 
            ActualPosition[1] !=   Labyrinth.ExitPoint[1]) //I'm not at the end..
        continue;

        PrintMyStatus(); //Print in the console my parents and my complete route..
        break;
    }

This is the Move() method:

List<int[]> validPaths = CheckSurroundings(); //returns a list of paths

switch (validPaths.Count)
{
    case 0:
        ImDone = true; //No more routes available
        break;
    case 1:
        MarkMyPosition(validPaths); //Change internal variables to the only new path
        break;
    default:
        lock(this) //As this involves thread creating I locked it..
        {
            //Creating deep copies of my "History" so my childs can have them..
            List<int[]> DCValidPaths = DeepCopy(validPaths);
            List<string> DCMyParents = DeepCopy(MyParents);
            string[,] DCMyExplorationMap = DeepCopy(MyExplorationMap);
            List<int[]> DCMyPositions = DeepCopy(MyPositions); 

            foreach (var path in validPaths)
            {
                DCMyParents.Add(Thread.CurrentThread.Name); //Adding myself as a parent

                ExplorationManager.ExplorerMaker(
                    DCValidPaths, 
                    DCMyParents, 
                    DCMyExplorationMap, 
                    DCMyPositions,
                    ID);  //Threads are created in the static class
            }
         }
    break;
}

My DeepCopy() method is using is the one in the accepted answer of this question. Any other info needed I'll be more than happy to provide in order to solve the problem. Thanks in advance for your help.

EDITS: My problem consists basically in: I'm having an OutOfMemoryException in the Thread.Start() clause and the Path displayed by the threads contain corrupted data (incorrect positions). I tested the CheckSurroundings() method and by far only returns correct positions (The labyrinth is contained in a two-dimensional string array).

This is the constructor of the Explorer class:

public Explorer(List<string> myParents, int[] actualPosition, string[,]   myExplorationMap, 
        List<int[]> myPositions, int ID)
    {
        //Here I pass the data specified in Move(); 
        MyParents = myParents;
        ActualPosition = actualPosition;
        MyExplorationMap = myExplorationMap;
        MyPositions = myPositions;
        this.ID = ID + 1; //An ID for reference

        //Marking position in my map with "1" so I know I've been here already,
        //and adding the position given to my list of positions
        MyExplorationMap[ActualPosition[0], ActualPosition[1]] = "1";
        MyPositions.Add(DeepCopy(ActualPosition));
    }

And this is the class creating the threads:

public static class ExplorationManager
{
    public static void ExplorerMaker(List<int[]> validPaths, List<string> myParents, string[,] myExplorationMap, List<int[]> myPositions, int ID)
    {
        foreach (var thread in validPaths.Select
            (path => new Explorer(myParents, path, myExplorationMap, myPositions,ID)).
            Select(explorer => new Thread(explorer.Explore)))
        {
            thread.Name = "Thread of " + ID + " generation"; 
            thread.Start(); //For each Path in Valid paths, create a new instance of Explorer and assign a thread to it.
        }
    }
}

And the method returning the ValidPaths

    private List<int[]> CheckSurroundings()
    {

        var validPaths = new List<int[]>();
        var posX = ActualPosition[0];
        var posY = ActualPosition[1];

        for (var dx = -1; dx <= 1; dx++)
        {
            if (dx == 0 || (posX + dx) < 0 || (posX + dx) >= Labyrinth.Size ||
                MyExplorationMap[posX + dx, posY] == "1") continue;
            var tempPos = new int[2];
            tempPos[0] = posX + dx;
            tempPos[1] = posY;
            validPaths.Add(tempPos);
        }

        for (var dy = -1; dy <= 1; dy++)
        {
            if (dy == 0 || (posY + dy) < 0 || (posY + dy) >= Labyrinth.Size ||
                MyExplorationMap[posX, posY + dy] == "1") continue;
            var tempPos = new int[2];
            tempPos[0] = posX;
            tempPos[1] = posY + dy;
            validPaths.Add(tempPos);
        }
        //This method checks up, down, left, right and returns the posible routes as `int[]` for each one
        return validPaths;
    }

CheckSurroundings uses the deep copy passed to the child (via the constructor) to validate the routes he can take. It is NOT intended to alterate the parent's copy, because he is now in ANOTHER path of the labyrinth. The child only needs the information updated (passed via the constructor) UNTIL the point they "separate". And also EACH child must be independent from the other childs. That's what I'm trying to do. But I'm not sure what's wrong, maybe concurrency problem? Please help. If you need anything else let me know. –

Community
  • 1
  • 1
  • **Just a side note:** please don't include tags in the title, unless it's absolutely necessary. You've already tagged the question as C#, there is no need to say C# in the title. – Kiril Oct 19 '12 at 15:20
  • I've been looking through the code and it's not immediately obvious to me what's the problem you're encountering. What do you mean when you say that your output is "all messed up"? What is your output, what are you expecting it to be, is there other relevant code? – Kiril Oct 19 '12 at 15:24
  • Define "all messed up". What's actually happening when you run this code? – Tim Copenhaver Oct 19 '12 at 15:27
  • Just edited the question. I can post any other code needed, just posted the code I thought that was giving the problem in order to make the question smaller. – Jean Carlos Suárez Marranzini Oct 19 '12 at 15:29
  • @Lirik Any other information I'll provide instantly. All for the good of the answer. – Jean Carlos Suárez Marranzini Oct 19 '12 at 15:40
  • @TimCopenhaver Any other information I'll provide instantly. All for the good of the answer. – Jean Carlos Suárez Marranzini Oct 19 '12 at 15:43
  • If you're getting an OutOfMemoryException, then please post the Thread.Start() code and any other relevant code. Is Path a collection that's being populated by the threads? If so, how do you ensure that the threads are correctly and safely add nodes to the path? – Kiril Oct 19 '12 at 15:52
  • @Lirik The functionality im trying to implement is this one: -A thread moves and moves, and keeps updating its own current position, route, and map. -When a thread finds a bifurcation, takes the first path, and then creates a thread for each other available path he found in a bifurcation, so he passes just the values of its own history (map, parents, positions) and the path that the child must start on. After that they are completely independent (Or at least that's my intention) – Jean Carlos Suárez Marranzini Oct 19 '12 at 16:14
  • @Lirik Just updated the question with more code. – Jean Carlos Suárez Marranzini Oct 19 '12 at 16:16

1 Answers1

1

EDIT for your updates:

myExplorationMap is a deep copy of the original exploration map. You set the position to 1 in the Explorer constructor, which updates the copy that is shared by all of the child threads, but it does not update the original MyExplorationMap property in the parent thread. Only the child threads will know this position was visited. I assume this is used somewhere in the CheckSurroundings method?

Tim Copenhaver
  • 3,282
  • 13
  • 18
  • I updated the question... I really appreciate your help! Any other info just tell me. Each threads has its own copy of valid paths because is local, I only pass a list with the paths that the childs have to START on, so it shouldn't be interacting with his parents. He only needs to know the "history" until the moment of it's creation. After that they are independent. – Jean Carlos Suárez Marranzini Oct 19 '12 at 16:08
  • That is completely correct. My intention is exactly that one. `CheckSurroundings` uses the deep copy passed to the child (via the constructor) to validate the routes he can take. It is NOT intended to alterate the parent's copy, because he is now in ANOTHER path of the labyrinth. The child only needs the information updated (passed via the constructor) UNTIL the point they "separate". And also EACH child must be independent from the other childs. That's what I'm trying to do. But I'm not sure what's wrong, maybe concurrency problem? Please help. If you need anything else let me know. – Jean Carlos Suárez Marranzini Oct 19 '12 at 16:29
  • 1
    This is only true until you have two descendant threads (maybe 2 or 3 children down) that end up running into each other. They will never run the same path as their shared parent, but it's still possible for two separate descendant trees to re-traverse the same area multiple times. – Tim Copenhaver Oct 19 '12 at 16:54
  • Well, if they are separate trees of childs, they can traverse through other paths as long as the paths weren't visited before in its own tree of threads, because there are multiple ways to solve the same maze, and because I suppose that eventually each thread will either have no possible route, or will arrive to the exit (that's why I pass a copy of `MyExplorationMap`). Is my assumption correct based on this code? And if it is correct, why the data of the positions traveled by each thread getting corrupted? – Jean Carlos Suárez Marranzini Oct 19 '12 at 16:59
  • Everything ok? Any other information needed? I'm really having a hard time here trying to solve this. – Jean Carlos Suárez Marranzini Oct 19 '12 at 17:54