EventHandler: Что происходит в этом коде? - PullRequest
5 голосов
/ 05 февраля 2012

этот код, который добавляет регистры новых EventHandler (ов) для события с именем NewMail (класс 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<NewMailEventArgs> 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<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);
}

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

1 Ответ

3 голосов
/ 05 февраля 2012

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

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

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

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

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

...