На данный вопрос уже ответили:
Рихтер пишет, что делегат "за кулисами" раскладывается в такую штуку:
// 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
? В чем суть этого цикла. Что-то до конца не понимаю.
Методы класса Interlocked
являются атомарными операциями, а значит они работают быстрее чем lock
.
Общий совет такой, если какую-то задачу можно сделать с использованием Interlocked
, то лучше использовать его, а не lock
. lock
может загнать выполняющий поток в режим Sleep
, а это повлечет замедление в работе.
Детальней написано здесь: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/
Несмотря на то, что в вашем примере кажется, что цикл может выполнятся бесконечно, на практике никто не будет спамить в другом потоке бесконечные добавления/удаления событий. Если произойдет одиночный конфликт, цикл выполнится 2 раза вместо одного. При этом поток не войдет в режим сна, а всего лишь сделает несколько дополнительных простых операций.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Привет всемРебят, не могу понять, как вообще можно сделать кастомное меню? Вот к примеру у меня есть UserControl:
Я сильно запуталсяWinForms, использую библиотеку Afforge, их пространства имен - AForge
Консоль закрывается после нажатия любой клавиши, ни как не могу понять где ошибка, подскажите кто работал с этой библиотекой