Как C # EventHandler работает внутри? - PullRequest
4 голосов
/ 21 ноября 2011

Я предполагаю, что у обработчика событий C # есть список слушателей, и он перебирает список при отправке сообщения. Мой вопрос: как это работает внутри? Делает ли он копию списка до его повторного выполнения, и если да, то что произойдет, если кто-то отменит свою регистрацию после того, как список будет скопирован, но он еще не получил сообщение.

Будет ли оно по-прежнему получать сообщение, даже если оно само незарегистрировано?

1 Ответ

6 голосов
/ 21 ноября 2011

Делегат является неизменным, поэтому при вызове делегата список подписчиков известен и фиксирован. Подписка или отмена подписки заменяет делегата, который поддерживает событие.

Это действительно означает, что в многопоточном сценарии вы можете получить событие после отказа от подписки, потому что либо:

  1. делегат уже находился в процессе вызова
  2. снимок делегата уже был получен для цели вызова

2, я имею в виду обычный шаблон (для предотвращения нулевого ref во время вызова):

var handler = SomeEvent;
// <===== another thread could unsubscribe at this point
if(handler != null) handler(sender, args); // <== or part way through this invoke
// (and it either case, have the event trigger even though they think they have
// unsubscribed)

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

Эти нюансы не влияют на однопоточный код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...