Подход BeginInvoke
является асинхронным, что означает, что он вызывается в другом потоке.Это может быть опасно, если люди этого не ожидают, и довольно редко для событий - но это может быть полезно.
Также обратите внимание, что строго говоря вы должны сделать снимок значения обработчика события- это особенно true, если (через Begin*
) вы имеете дело с потоками.
var tmp = _myEventHandler;
if(tmp != null) {
tmp(sender, args);
}
Также обратите внимание, что ваша подписка на событие сама не является потоком-безопасный;Опять же, это имеет значение, только если вы имеете дело с многопоточностью, но встроенное поле-событие является поточно-безопасным:
public event EventHandler<MyEventArgs> MyEvent; // <===== done; nothing more
Здесь избегаются следующие проблемы:
- с помощью моментального снимка мы избегаем риска, когда последний подписчик отписался между нулевой проверкой и вызовом (это означает, что они могут получить событие, которого они не ожидали, но это означает, что мы не убиваемподнимающий поток)
- с изменением события, подобного полю, мы избегаем риска потери подписок / отписок, когда два потока делают это одновременно