2012-02-05 7 views
5

ten kod, który dodaje rejestruje nowe Podprogram (y) na imprezę o nazwie jak NewMail (klasa EventArgs nazwie NewMailEventArgsEventHandler: Co się dzieje w tym kodzie?

// 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); 
} 

(źródło:. CLR za pośrednictwem C#, rozdział 11 zdarzeń) Czego nie robić rozumiem, że jest to część, najpierw przypisujemy newMail do prevHandler, następnie newMail jest zmieniany (w CompareExchange) na newHandler ?, a następnie sprawdzamy, czy newMail! = prevHandler?
Jestem naprawdę trochę zmieszany. Czy ktoś może mi pomóc zrozumieć, co to jest dokładnie dzieje się tutaj, szczególnie w pętli "do"?

Odpowiedz

3

Jako komentarz mówi, że jest to rodzaj bezpiecznego sposobu radzenia sobie z wydarzeniami w środowisku wielowątkowym. Jest to dość trudne, faktycznie, ale oto jak to działa:

  • Co Interlocked.CompareExchange jest: if prevHandler == this.NewMail, następnie this.NewMail = newHandler

  • Cała operacja (por + wpływać) jest atomowy, tj odbywa się w jeden raz (nie można zatrzymać w trakcie operacji przez inny wątek).

  • Jeśli NewMail nie jest równa prevHandler, oznacza to inny wątek uruchomiono już sam kod i już modyfikacji procedury obsługi zdarzeń. Tak więc nic tu nie zrobimy i zaczniemy pętlę i spróbujemy ponownie, mając nadzieję, że następnym razem jest żaden inny wątek, który już zarejestrował obsługę zdarzeń (następnym razem będziemy ponownie przeczytać program obsługi zdarzeń; operacja wykonana przez drugi wątek zostanie teraz wzięta pod uwagę).

Zobacz także przydatny thread.