2012-10-27 4 views
0

가능한 중복 :
C# - The foreach identifier and closures
From Eric Lippert’s blog: “don’t close over the loop variable”람다 식

내가 사용하는 새 스레드에서 메소드를 실행하려면 ThreadStart 매개 변수로 람다 식을 사용하고 있습니다 Thread 클래스. 이건 내 코드입니다 :

delegate void del(); 

static void Do(int i) 
{ 
    Console.WriteLine(i); 
} 

static del CreateLoop(del Do) 
{ 
    return() => 
    { 
     while (true) 
     { 
      Do(); 
      Thread.Sleep(500); 
     } 
    }; 
} 

static void Main(string[] args) 
{ 
    int n = 0; 
    var loop = CreateLoop(() => Do(n)); 
    new Thread(() => loop()).Start(); 
    Thread.Sleep(500); 
    n = 1; 
} 

그리고 이것은 출력 :

0 
1 
1 
1 
... 

어떻게 가능합니까?
정수 변수 n의 값을 변경하면 i (Do의 매개 변수) 값도 변경됩니까?

+0

@ L.B 그게 변수 범위에 대한 캡처 된 변수에 관한 ... – gliderkite

+1

gliderkite, 그래서 당신은 전에 아무도 직면하지 아주 특별한 경우에 충돌? 참조를 다시 읽으십시오. –

답변

0

다른 변수를 만들어서 원래 값을 변경하지 않아야합니다.

결국 당신이 실제로하고있는 것은 동일한 오래된 '함수'를 호출하는 것입니다. 람다 표현식은 변수 i를 반복해서 전달하며 실제로 변경됩니다. 그것은 var n의 어딘가에 초기 값을 저장하는 것과 같은 것이 아닙니다.

0
var loop = CreateLoop(() => Do(n)); 

이 줄은 단순히 새로운 함수를 만들고 변수에 할당하는 것입니다. 이 함수는 무엇보다도 n 값을 Do 함수에 전달합니다. 그러나 그것은 Do 함수를 호출하지 않습니다. 함수가 실행될 때 Do 함수를 호출하는 것입니다.

그런 다음 함수 등을 호출하는 새 스레드를 시작하지만 새 스레드는 여전히 Do(n)을 실행하고 에 n 변수를 전달합니다. 그 부분은 변경되지 않습니다 - 변수 (n 변수로 표시)의 특정 위치를 참조하는 함수를 생성하고 거기에 저장된 값을 변경하는 경우에도 해당 위치를 메모리에서 계속 참조합니다.

나는 다음이 코드를 "수정"할 생각 :이 loop가 나타내는 함수 n의 값을 전달

var loop = (int x) =>() => CreateLoop(() => Do(x)); 
new Thread(loop(n)).Start(); 

을하지만, loop 기능은 메모리에 새로운 장소를 만들어 (x으로 표시) 값을 저장하는 데 사용됩니다. 메모리에있는이 새 위치는 n의 이후 변경으로 인해 영향을받지 않습니다. 즉, 작성한 함수는 n이 포인터 인 메모리상의 장소를 직접 참조하지 않습니다.