2011-02-09 1 views
4

У меня есть следующий код, который я использую для имитации живой передачи данных, которая одновременно отправляет сообщение, что каждый объект типа «Символ» в коллекции внутри «Портфолио.Symbols» должен реагировать (другим способом, выполняющим над ним некоторые работы).Несколько анонимных обработчиков событий - но только последний называется

Для того, чтобы это было правдой одновременно, я пытаюсь зарегистрировать анонимный обработчики событий следующим образом:

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 (и различные ссылки в верхней части и комментарии). Это очень популярный вопрос SO. – Brian

ответ

10

Печально известная ошибка перехватчика/foreach; попробуйте:

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

and 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 - ничего * действительно *, за исключением того, что вам нужно понять, что «захваты» происходят в области декларации переменной, и * технически * переменная 'symbol' объявлена ​​** вне ** цикла; вы захватываете 1 ** переменную ** - то же самое каждый раз. Перемещая область «copy» внутри цикла, вы фиксируете (с точки зрения логики) другую переменную на итерацию. –

+0

@Saul - обратите внимание также на мои заметки о событии - и со всей серьезностью: статические события редко бывают хорошей идеей –