2011-02-09 3 views
4

라이브 데이터 피드를 시뮬레이트하는 데 사용하는 다음 코드가 있습니다. 은 "Portfolio.Symbols"컬렉션의 각 개체 "Symbol" (다른 방법으로 그것에 대한 작업을해야 함)에 응답해야합니다. ,복수의 익명 이벤트 처리기 - 마지막 하나만 호출됩니다.

static public void RegisterEvents() 
{ 
    foreach (Symbol symbol in Portfolio.Symbols) 
    { 
     GenerateQuoteRequest +=() => { SomeMethod(symbol); }; 
    } 
} 

static public void Run() 
{ 
    OnGenerateQuoteRequest(); 
    Thread.Sleep(100); 
} 

public delegate void OnGenerateQuoteRequestEventHandler();  
public static event OnGenerateQuoteRequestEventHandler GenerateQuoteRequest 
              = delegate {}; 
... 

내가 다음 이벤트를 마련하려고 내가 "것으로 someMethod의 번호를 얻을 것이다 희망 : 동시에, 나는 익명의 이벤트 핸들러를 다음과 같은 방법을 등록하려고 진실하기 위해서는

"인스턴스가 실행됩니다. 불행히도 추가 된 마지막 "심볼"만 호출됩니다.

무엇이 여기에 있습니까?

+2

에만 호출됩니다 추가 된 마지막 "기호"- 그래,하지만이 많은라고합니다. –

+0

http://stackoverflow.com/questions/3190578/from-eric-lipperts-blog-dont-close-over-the-loop-variable (상단 및 의견에있는 다양한 링크)도 참조하십시오. 이것은 매우 인기있는 질문입니다. – Brian

답변

10

악명 높은 캡처 된 변수/foreach 글리치. 시도 :

foreach (Symbol symbol in Portfolio.Symbols) 
{ 
    var copy = symbol; 
    GenerateQuoteRequest +=() => { SomeMethod(copy); }; 
} 

및 btw; static event s는 입니다. 실제로 위험합니다. 이러한 이벤트 구독은 자체적으로 구독을 취소하지 않으므로 불필요하게 많은 것을 메모리에 보관할 수 있습니다. 당신은 물론, 그 자체 구독 취소 할 수 있습니다 :

foreach (Symbol symbol in Portfolio.Symbols) 
{ 
    var copy = symbol; 
    OnGenerateQuoteRequestEventHandler handler = null; 
    handler =() => { 
     SomeMethod(copy); 
     GenerateQuoteRequest -= handler; 
    }; 
    GenerateQuoteRequest += handler; 
} 
+0

그게 효과가 ... 정확히 내가 뭘 잘못 했니? – Saul

+0

@Saul - 아무것도 * 정말로 *, 당신은 "캡쳐"가 변수의 선언 범위에서 일어나고, 기술적으로 * 변수'심볼'이 ** 루프 외부에서 ** 선언된다는 것을 이해해야한다는 것을 제외하고는; 당신은 1 ** 변수 ** - 매번 같은 것을 포착합니다. 루프 내에서'copy '의 범위를 이동시킴으로써, 당신은 반복마다 다른 변수를 (로직 측면에서) 캡쳐합니다. –

+0

@Saul - 이벤트에 관한 내 노트와 모든 진지함에도 유의하십시오. 정적 이벤트는 거의 좋은 아이디어가 아닙니다. –