Intereting Posts
C # нулевой коалесцирующий оператор-эквивалент для c ++ Как я могу проанализировать Decimal.TryParse 0.0? Как удалить MSI с помощью кода продукта в c # явно ссылаются на class без пространства имен в C # Должен ли я вызвать параметр. Устранимо при повторном использовании SqlCommand с трансацией? Как развернуть автономное приложение Owin в производстве? Почему имена участников C # не могут быть такими же, как имя типа вложения? Выбор узла с несколькими значениями пространства имен в документе XML ничего не возвращает ожидание без ConfigureAwait (false) продолжается в другом streamе Компиляция даты и времени Наследовать class Exception для регистрации всех последующих случаев исключения Заголовки CORS отсутствуют при развертывании в Azure Web App / Azure API DataTable с байтом в качестве параметра хранимой процедуры Предоставление унаследованных статических свойств (концептуально) В чем разница между этими объявлениями массива?

EventHandler: Что происходит в этом коде?

этот код добавляет регистры new EventHandler (s) для события с именем NewMail (class eventargs имеет имя NewMailEventArgs .

 // A PUBLIC add_xxx method (xxx is the event name) // Allows methods to register interest in the event. public void add_NewMail(EventHandler value) { // The loop and the call to CompareExchange is all just a fancy way // of adding a delegate to the event in a thread-safe way. EventHandler prevHandler; EventHandler newMail = this.NewMail; do { prevHandler = newMail; EventHandler newHandler = (EventHandler)Delegate.Combine(prevHandler, value); newMail = Interlocked.CompareExchange<EventHandler>(ref this.NewMail, newHandler, prevHandler); } while(newMail != prevHandler); } 

(источник: CLR через C #, глава 11 События) То, что я не понимаю, является частью do, сначала мы назначаем newMail prevHandler, затем newMail изменяется (в CompareExchange) на newHandler? Затем мы проверяем, будет ли newMail! = PrevHandler?
Я действительно смущен. Может ли кто-нибудь помочь мне понять, что именно происходит здесь, особенно в цикле do?

Как отмечается в комментарии, это должно стать своего рода безопасным способом борьбы с событиями в многопоточной среде. На самом деле это довольно сложно, но вот как это работает:

  • Что такое Interlocked.CompareExchange : if prevHandler == this.NewMail , затем this.NewMail = newHandler

  • Вся операция (compare + impact) является атомарной , т. Е. Выполняется за один раз (не может быть остановлена ​​в середине операции другим streamом).

  • Если NewMail не равен prevHandler , значит, другой stream уже prevHandler один и тот же fragment кода и уже модифицировал обработчик событий . Таким образом, мы ничего здесь не будем делать, и мы зациклимся и попробуем еще раз, надеясь , что в следующий раз нет другого streamа, который уже зарегистрировал обработчик событий (в следующий раз мы перечитаем обработчик событий, а другая операция stream будет теперь учтен).

См. Также эту полезную тему .