2011-01-19 2 views
0

은 내가 이렇게 보이는 실버 코드 숨김 코드의 조각을 가지고 :Dispatcher.beginInvoke는 루프를 통해 마지막 시간 만 실행합니까?

foreach (MapLocation loc in e.Result) 
     { 

      testDict[loc.ElemId] = loc.ToString(); 

      this.Dispatcher.BeginInvoke(delegate() 
      { 
       Image icon = new Image(); 
       icon.SetValue(Image.SourceProperty, nurseIconSource); 
       Canvas.SetLeft(icon, (double)loc.X * MAP_SCALE); 
       Canvas.SetTop(icon, MAP_HEIGHT - (double)loc.Y * MAP_SCALE); 
       icons[loc.ElemId] = icon; 
       MainCanvas.Children.Add(icon); 
      }); 
     } 
    } 

이 루프는 UI 스레드에서 별도의 스레드에서 25 번 실행됩니다. testDict 객체는 메소드 실행 후 25 개의 모든 항목으로 끝나고 아이콘 사전은 25 번째 항목에 대한 항목 만 저장합니다.

Dispatcher를 처음 사용했습니다. 이런 급한 불이라고 부를만한 것이 아닌가? 내가 생각할 수있는 것은 위임자가 처음으로 호출 된 것은 루프를 마지막으로 지나친 것이므로 loc 객체는 항상 동일한 항목이라는 것입니다. 정확합니까?

답변

5

이전의 "루프 변수를 캡처하지 않음"문제입니다. 이것은 많은 사람들을 잡습니다. 대리인이 항상 loc현재 값을 사용하고 ... 그리고 대의원 실행하기 전에 이미 루프를 완료 한 경우, 즉 loc의 마지막 값을 의미합니다 실행할 때

기본적으로 표시됩니다 여러 번 기본적으로. 익명있어서 내부

foreach (MapLocation loc in e.Result) 
{ 
    MapLocation copy = loc; 
    testDict[loc.ElemId] = loc.ToString(); 

    this.Dispatcher.BeginInvoke(delegate() 
    { 
     Image icon = new Image(); 
     icon.SetValue(Image.SourceProperty, nurseIconSource); 
     Canvas.SetLeft(icon, (double)copy.X * MAP_SCALE); 
     Canvas.SetTop(icon, MAP_HEIGHT - (double)copy.Y * MAP_SCALE); 
     icons[copy.ElemId] = icon; 
     MainCanvas.Children.Add(icon); 
    }); 
} 

주 "복사"를 사용하는 대신 "LOC"

해결책은 루프 변수의 복사본을 작성하는 것이다.

자세한 내용은 Eric Lippert의 블로그 게시물 "유해한 것으로 간주되는 루프 변수 닫기"- part one을 읽어보십시오. part two.

+0

감사합니다. 좋은 기사 너무. – Erix

1

반복 변수를 닫습니다. 해결 방법은 loc 내부의 임시 변수에 loc을 할당하는 것입니다.

foreach (MapLocation location in e.Result) 
    { 
     //assign temp variable here. 
     MapLocation loc = location; 
     //... 
    } 
관련 문제