2012-10-19 67 views
0

我在編寫一個應用程序時遇到了一些問題。這是工作是使用線程解決迷宮。一個線程開始,並且對於每個分支它調用另一個類中的靜態方法,傳遞另一個線程需要的參數,然後爲每個路徑啓動線程。我的輸出都搞砸了,我不確定這是多線程問題還是與引用有關的問題。下面是一些代碼(每個線程都被賦予一個Explorer類的新實例):多線程並將數據傳遞到新線程

這是每個線程的Run()方法:

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

這是Move()方法:

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

我的DeepCopy()方法正在使用的是在this接受答案的問題。需要其他任何信息我將非常樂意提供以解決問題。在此先感謝您的幫助。編輯:我的問題基本上在於:我在Thread.Start()子句中有一個OutOfMemoryException和由線程顯示的路徑包含損壞的數據(不正確的位置)。我測試了CheckSurroundings()方法,到目前爲止只返回正確的位置(迷宮包含在一個二維字符串數組中)。

這是Explorer類的構造函數:

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

CheckSurroundings使用傳遞給孩子的深層副本(通過構造uctor)驗證他可以採取的路線。它並不打算改變父母的副本,因爲他現在正處於迷宮的另一條路上。孩子只需要更新信息(通過構造函數傳遞)直到他們「分離」的點。而且每個孩子都必須獨立於其他孩子。這就是我想要做的。但我不確定有什麼問題,可能是併發問題?請幫忙。如果你需要其他東西,請告訴我。 -

+0

**只是旁註:**請不要在標題中加入標籤,除非絕對必要。您已經將問題標記爲C#,標題中不需要說C#。 – Kiril

+0

@李克羅傑羅傑,謝謝。 –

+0

我一直在尋找代碼,它並不是很明顯,我遇到了什麼問題。當你說你的輸出「​​全搞砸了」是什麼意思?你的輸出是什麼,你期待它是什麼,還有其他相關的代碼嗎? – Kiril

回答

1

編輯您的更新:

myExplorationMap是原始的探索地圖的深層副本。在Explorer構造函數中將位置設置爲1,該構造函數更新所有子線程共享的副本,但不會更新父線程中的原始MyExplorationMap屬性。只有子線程會知道這個位置被訪問過。我認爲這是用在CheckSurroundings方法的某個地方?

+0

我更新了問題......我非常感謝您的幫助!任何其他信息只是告訴我。每個線程都有自己的有效路徑副本,因爲它是本地的,我只通過一個列表,其中包含子節點必須啓動的路徑,所以它不應與父母進行交互。他只需要知道「歷史」直到它創作的那一刻。之後,他們是獨立的。 –

+1

在您的更新中添加了另一個想法 –

+0

這是完全正確的。我的意圖正是這一個。 'CheckSurroundings'使用傳遞給孩子的深度拷貝(通過構造函數)來驗證他可以採用的路線。它並不打算改變父母的副本,因爲他現在正處於迷宮的另一條路上。孩子只需要更新信息(通過構造函數傳遞)直到他們「分離」的點。而且每個孩子都必須獨立於其他孩子。這就是我想要做的。但我不確定有什麼問題,可能是併發問題?請幫忙。如果你需要其他東西,請告訴我。 –