2013-12-10 58 views
2

我對C#線程相當陌生,所以提前爲這個新手錯誤道歉。以下代碼的目標是評估存儲在名爲members的數組中的總體的適應性。程序members.calculateFitness()是一個黑盒子(即我不能修改它來提高性能),所以我試圖設置線程來同時調用黑匣子,並且每個線程將處理1/THREAD_COUNT羣體成員(所以如果THREAD_COUNT = 4,每個線程將處理總人口的1/4)。線程修改意外變量

在第一個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異常。我可以看到,我= THREAD_COUNT(我用THREAD_COUNT的不同號碼嘗試過)。

我完全不解,我做錯了什麼? 在此先感謝!

enter image description here

+2

你關閉了循環變量('i')。 – Servy

+0

您應該查看[Task](http://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task%28v=vs.110%29.aspx)類,而不是創建自己的以這種方式線程。 'Task'使用一個線程池,這是99%的情況下你想要的。 – MgSam

+0

@Servy當海報不知道問題是什麼時,這是如何重複的?這不像他問「爲什麼我不能關閉循環變量」。你只是鼓勵新用戶不要使用這個網站,因爲當有人甚至不理解這個問題時,他們會對重複進行過激的攻擊。 – MgSam

回答

0

Servy有它發現的,我甚至還記得現在約翰飛碟雙向的書中讀到這一點。我不得不在for循環中創建一個副本,這固定了它。

謝謝!

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