当前位置: 首页 > 知识库问答 >
问题:

多线程和将数据传递到新线程

谭骏
2023-03-14

我在编写一个应用程序时遇到了一些问题。它的工作是用线来解决迷宫。一个线程开始,对于每个分支,它调用另一个类中的静态方法,传递另一个线程需要的参数,然后为每个路径启动线程。我的输出都搞乱了,我不确定这是多线程问题还是引用的问题。下面是一些代码(每个线程都有一个explorer类的新实例):

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;
    }
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;
}
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));
    }
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.
        }
    }
}

和返回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;
    }

CheckEnvirondings使用传递给子级的深度副本(通过构造函数)来验证子级可以采用的路由。它并不打算改变父母的副本,因为他现在在迷宫的另一条路径上。子级只需要更新信息(通过构造函数传递),直到它们“分离”为止。而且每个孩子都必须独立于其他孩子。这就是我想做的。但我不确定是什么问题,也许是并发问题?请帮忙。如果你还需要什么,请告诉我。-

共有1个答案

咸利
2023-03-14

编辑您的更新:

myExplorationMap是原始勘探地图的深度拷贝。在资源管理器构造函数中将位置设置为1,这将更新所有子线程共享的副本,但不会更新父线程中的原始MyExplorationMap属性。只有子线程才知道这个位置被访问过。我假设这是在CheckEnvirondings方法中的某个地方使用的?

 类似资料:
  • 问题内容: 我正在编写的应用程序在某个阶段会生成一个ArrayList of Characters。在此阶段,我正在尝试创建一个线程来处理此ArrayList。问题是如何将这个ArrayList传递给线程 描述代码: ProcessList的描述性代码: 我的问题是:如何在run()中传递和访问aList? 问题答案: 您可以简单地传递给的构造函数,该构造函数可以保留引用,直到需要它为止: 注意:

  • 我在C 11应用程序中有长时间运行的功能,基本上是。我需要通知这个函数在不同线程中出现。要求: 可以随时上升。 应用程序最多只能在一个地方处理(也可以不处理)。 它不需要超快速执行,也不需要延迟执行 截至目前,我考虑了两种选择: 传递包含。然后在<code>sub_main</code>内定期轮询对象,以了解新的<code>情况</code>。轮询对象已从队列中删除。当应用程序决定不处理特定位置的

  • 本文向大家介绍C#程序将参数传递给线程,包括了C#程序将参数传递给线程的使用技巧和注意事项,需要的朋友参考一下 要使用线程,请在代码中添加以下命名空间- 首先,您需要在C#中创建一个新线程- 上面,threadDemo是我们的线程函数。 现在将参数传递给线程- 上面设置的参数是- 示例 让我们看完整的代码,以将参数传递给C#中的线程。 输出结果

  • 根据http://wiki.apache.org/jmeter/JMeterFAQ我应该能够在jmeter Gui中指定jmeter测试计划的用户/线程数,如下所示: 其中defaultvalue可以是1,2,3,无论什么。。。 当我尝试这样做时,我的测试甚至没有开始。 有什么提示吗? 谢谢

  • 问题内容: 谁能建议我如何将参数传递给线程? 另外,它如何用于匿名类? 问题答案: 你需要将构造函数中的参数传递给Runnable对象: 然后调用它:

  • 我试图更多地熟悉Redis,我发现Redis6的发行说明如下: Redis6进入了一个新时代:虽然它保留了一个核心的单线程数据访问接口,但I/O现在是线程化的。 保留“核心单线程数据访问接口”是否意味着所有数据访问命令(如GET、SET),无论redis实例中的哪个数据库,都必须通过这个接口(而不是使用多个redis实例时的多个数据访问接口)? 谢了!