2010-08-19 15 views
23

Es posible ejecutar el siguiente código desde múltiples hilos simultáneamente.Agregar delegado al evento - seguridad de hilos

this._sequencer.Completed += OnActivityFinished; 

¿Es seguro agregar delegado a un controlador de eventos desde varios subprocesos?

¿Es seguro quitar el hilo delegado a partir de controlador de eventos desde múltiples hilos?

¿Cuál es la manera más simple y fácil de mantener de hacer de este hilo seguro?

Respuesta

31

Si no se especifica su propio evento añadir/quitar los controladores, el compilador de C# genera este controlador complemento (reconstruido por .NET Reflector):

public void add_MyEvent(EventHandler value) 
{ 
    EventHandler handler2; 
    EventHandler myEvent = this.MyEvent; 
    do 
    { 
     handler2 = myEvent; 
     EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value); 
     myEvent = Interlocked.CompareExchange<EventHandler>(ref this.MyEvent, handler3, handler2); 
    } 
    while (myEvent != handler2); 
} 

y un controlador quitar que parece lo mismo pero con Delegate.Remove en lugar de Delegate.Combine.

Aviso el uso de Interlocked.CompareExchange? Esto evita una condición de carrera entre la actualización del campo de respaldo del evento y la lectura de él. Por lo tanto, es seguro para subprocesos.

+2

una pequeña Clarificación- esta es la implementación en .NET 4, antes de que se utiliza 'bloqueo (este)' (véase también la respuesta de desco) –

+0

@ohadsc Acabo de crear un evento y se compile contra .net 2 y todavía se creó el Interlocked código según lo define timwi – Simon

+4

@Simon tienes razón, es una característica de compilación, no de tiempo de ejecución. Debería haber dicho "esta es la implementación en el compilador C# 4" –

4

Depende de la implementación del evento, para ser honesto.

Los eventos de campo como generados por el compilador de C# son hilos de proceso seguro, pero si es un evento personalizado, ¿quién sabe?

Tenga en cuenta que en una aplicación multi-roscado que debe esperar una condición de carrera entre añadir/eliminar un controlador y el evento de disparo ... por ejemplo, el evento puede empezar al fuego, usted podría entonces darse de baja, y su el manejador aún sería llamado después de esa desuscripción.

5

para eventos de tipo campo agregar/quitar manejadores es seguro para subprocesos. A partir de especificaciones:

Al compilar un evento de campo como, el compilador crea automáticamente de almacenamiento para guardar el delegado, y crea descriptores de acceso para el caso de que agregar o quitar controladores de eventos al campo delegado. Para que sea seguro para subprocesos, las operaciones de adición o eliminación se realizan mientras se mantiene el bloqueo (§8.12) en el objeto contenedor para un evento de instancia, o el objeto tipo (§7.6.10.6) para un evento estático.

Sin embargo, es cierto para C# 3.0 y menor, en C# 4.0 compilador genera implementación libre de bloqueo usando rutinas entrelazadas (pero especificación sigue siendo el mismo - error)

En implementaciones personalizadas nadie puede decir exactamente ... excepto tal vez el autor del código :)

+0

Creo que la especificación se ha actualizado, pero la versión actualizada no se ha publicado todavía. –

+0

tal vez, me refiero a la versión disponible aquí (fecha de publicación \t 4/19/2010) - http://www.microsoft.com/downloads/details.aspx?FamilyID=dfbf523c-f98c-4804-afbd-459e846b268e&displaylang=en – desco

Cuestiones relacionadas