Реализация делегата “за кулисами” [дубликат]

245
05 декабря 2017, 18:28

На данный вопрос уже ответили:

  • Реализация Event 1 ответ

Рихтер пишет, что делегат "за кулисами" раскладывается в такую штуку:

// 1. ЗАКРЫТОЕ поле делегата, инициализированное значением null
private EventHandler<NewMailEventArgs> NewMail = null;
// 2. ОТКРЫТЫЙ метод add_Xxx (где Xxx – это имя события)
// Позволяет объектам регистрироваться для получения уведомлений о событии
public void add_NewMail(EventHandler<NewMailEventArgs> value) {
// Цикл и вызов CompareExchange – хитроумный способ добавления
// делегата способом, безопасным в отношении потоков
EventHandler<NewMailEventArgs>prevHandler;
EventHandler<NewMailEventArgs> newMail = this.NewMail;
do {
    prevHandler = newMail;
    EventHandler<NewMailEventArgs> newHandler =
   (EventHandler<NewMailEventArgs>) Delegate.Combine(prevHandler, value);
   newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(
   ref this.NewMail, newHandler, prevHandler);
} while (newMail != prevHandler);
}
// 3. ОТКРЫТЫЙ метод remove_Xxx (где Xxx – это имя события)
// Позволяет объектам отменять регистрацию в качестве
// получателей уведомлений о cобытии
public void remove_NewMail(EventHandler<NewMailEventArgs> value) {
// Цикл и вызов CompareExchange – хитроумный способ
// удаления делегата способом, безопасным в отношении потоков
EventHandler<NewMailEventArgs> prevHandler;
EventHandler<NewMailEventArgs> newMail = this.NewMail;
do {
    prevHandler = newMail;
    EventHandler<NewMailEventArgs> newHandler =
   (EventHandler<NewMailEventArgs>) Delegate.Remove(prevHandler, value);
    newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(
    ref this.NewMail, newHandler, prevHandler);
} while (newMail != prevHandler);
}

Собственно, непонятен этот "хитроумный" способ добавления/удаления делегата.

Почему сделано именно так, а не через какой-нибудь lock? В чем суть этого цикла. Что-то до конца не понимаю.

Answer 1

Методы класса Interlocked являются атомарными операциями, а значит они работают быстрее чем lock.

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

Детальней написано здесь: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

Несмотря на то, что в вашем примере кажется, что цикл может выполнятся бесконечно, на практике никто не будет спамить в другом потоке бесконечные добавления/удаления событий. Если произойдет одиночный конфликт, цикл выполнится 2 раза вместо одного. При этом поток не войдет в режим сна, а всего лишь сделает несколько дополнительных простых операций.

READ ALSO
SideMenu. Как сделать подпункты

SideMenu. Как сделать подпункты

Привет всемРебят, не могу понять, как вообще можно сделать кастомное меню? Вот к примеру у меня есть UserControl:

263
Не отрабатывает событие нового кадра NewFrame Aforge

Не отрабатывает событие нового кадра NewFrame Aforge

Я сильно запуталсяWinForms, использую библиотеку Afforge, их пространства имен - AForge

308
Не срабатывает команда OnClientClick

Не срабатывает команда OnClientClick

Всем добрый день! Создаю на форме кнопку через код::

237
HidLibrary чтение нажатия кнопок с клавиатуры

HidLibrary чтение нажатия кнопок с клавиатуры

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

258