2013-12-10 3 views
2

저는 C# 스레딩에 상당히 익숙하기 때문에이 초보자 오류에 대해 미리 사과드립니다. 다음 코드의 목적은 members라는 배열에 저장된 모집단의 적합성을 평가하는 것입니다. members.calculateFitness() 프로 시저가 블랙 박스 (즉, 성능 향상을 위해 수정할 수 없음)이므로 블랙 박스를 동시에 호출하는 스레드를 설정하려고하며 각 스레드는 1/THREAD_COUNT 명의 멤버를 처리합니다. (THREAD_COUNT = 4이면 각 스레드는 인구의 1/4을 처리합니다).의도하지 않은 변수를 수정하는 스레딩

첫 번째 for 루프에서 각 스레드를 초기화합니다. 두 번째 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; 
    } 

는 루프에 대한 제 들어간 다음 루프 위로 첫번째로 점프하고, 정수 i에서 IndexOutOfBoundsException가 선언 보여준다. 나는 = THREAD_COUNT (THREAD_COUNT에 대해 다른 숫자로 시도했습니다)를 볼 수 있습니다.

나는 완전히 당황 스럽다. 내가 뭘 잘못하고 있니? 미리 감사드립니다.

enter image description here

+2

당신은 루프 변수를 통해 폐쇄하고 ('i') : 당신이 무엇을해야

로컬 변수에 값을 복사합니다. – Servy

+0

자신의 클래스를 만들지 말고 [Task] (http://msdn.microsoft.com/en-us/library/system.threading.tasks.task%28v=vs.110%29.aspx) 클래스를 조사해야합니다. 스레드를이 방식으로 사용합니다. 'Task'는 99 %의 경우에 원하는 스레드 풀을 사용합니다. – MgSam

+0

@Servy 포스터가 문제의 원인을 모를 때 어떻게 중복 될 수 있습니까? "왜 루프 변수를 닫을 수 없습니까?"라고 묻는 것처럼 아닙니다. 새로운 사용자가 문제를 이해하지 못하는 경우에도 복제본에 대해 너무 공격적으로 사이트를 사용하지 말라는 것이 좋습니다. – MgSam

답변

0

Servy은 내가 지금도 존 스키트의 책이에 대한 책을 읽은 기억에 자리가 있습니다. 나는 for 루프 안에서 i의 사본을 만들어야 만했다.

감사합니다.

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])); 
} 
관련 문제