2012-02-05 33 views
5

el código que agrega registros nuevo manejador de sucesos (s) para un evento denominado como NewMail (la clase EventArgs es nombrado NewMailEventArgsEventHandler: ¿Qué está pasando en este código?

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

(fuente:. CLR a través de C#, capítulo 11 Eventos) Lo que no hago entiendo es la parte do, primero asignamos newMail a prevHandler, luego newMail se cambia (en CompareExchange) a newHandler? Entonces estamos comprobando si newMail! = prevHandler?
Estoy realmente un poco confundido. ¿Alguien puede ayudarme a entender qué exactamente está sucediendo aquí, especialmente en el ciclo do?

Respuesta

3

As El comentario dice que es para proporcionar una especie de forma de seguridad para lidiar con eventos en entornos de subprocesos múltiples. Esto es bastante complicado en realidad, pero así es como funciona:

  • ¿Qué Interlocked.CompareExchange es: if prevHandler == this.NewMail, entonces this.NewMail = newHandler

  • Toda la operación (comparar + afecto) es atómica, es decir hecho en una vez (no se puede detener a la mitad de la operación por otro hilo).

  • Si NewMail no es igual a prevHandler, entonces significa otro hilo ya corrió la misma pieza de código y ya modificó el controlador de eventos. Entonces no haremos nada aquí e iremos y volveremos a intentarlo, esperando que la próxima vez haya ningún otro hilo que ya haya registrado un controlador de eventos (la próxima vez haremos vuelva a leer el controlador de eventos; la operación realizada por el otro subproceso se tendrá en cuenta ahora).

Véase también este útil thread.

Cuestiones relacionadas