2010-05-07 16 views
5

Estoy haciendo eventos personalizados para C# y, a veces, no funciona.Pregunta sobre eventos personalizados

Ésta es la forma en que estoy haciendo que el evento suceda:

private bool isDoorOpen; 
    public bool IsDoorOpen { 
     get { return isDoorOpen;} 
     private set { isDoorOpen = value; DoorsChangeState(this, null);} 
    } 

Y éstas son las declaraciones de eventos:

//events   
    public delegate void ChangedEventHandler(Elevator sender, EventArgs e); 
    public event ChangedEventHandler PositionChanged; 
    public event ChangedEventHandler DirectionChanged; 
    public event ChangedEventHandler BreaksChangeState; 
    public event ChangedEventHandler DoorsChangeState; 

Esto funciona siempre y cuando existen métodos asociados a los eventos, pero si no lo hay, arroja una excepción de ref nulo. ¿Qué estoy haciendo mal?

Respuesta

10

El método recomendado para llamar a un evento es

var handler = this.DoorsChangeState; 
if (handler != null) 
    handler(this, null); 

La razón para copiar el controlador local es encajona los cambios de controlador de eventos en otro hilo mientras se está comprobando para nulo.

EDIT: encontré el artículo que habla sobre las condiciones de carrera. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

+0

+1 no se dio cuenta del plantear problemas de seguridad allí y el hecho de que los eventos son inmutables. Gracias por el enlace. –

0

Si un evento no está suscrito cuando se dispara, se lanzará una NullReferenceException. Este es el comportamiento correcto, no algo que has hecho mal.

Usted debe verificar:

if(DoorsChangeState != null) 
{ 
    DoorsChangeState(this, null); // Only fire if subscribed to 
} 
0

Antes de invocar un evento que debe comprobar si el evento es nulo:

if (DoorsChangeState != null) 
    DoorsChangeState(this, null); 

Cuando DoorsChangeState es nula que significa que no hay oyentes en ese evento.

0

Debes comprobar si el evento está suscrito.

Utilizo este formulario estándar para lanzar todos mis eventos.

var temp = EventName; 
if(EventName!= null) 
    temp(this, null); 
4

Sé que esta pregunta se ha debatido (y contestado) varias veces aquí en SO.

también por aquí Tengo las siguientes métodos de extensión para hacer de este patrón más fácil de usar:

public static class EventHandlerExtensions 
{ 
    public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs 
    { 
     var temp = handler; 
     if (temp != null) 
     { 
      temp(sender, args); 
     } 
    } 

    public static void FireEvent(this EventHandler handler, object sender) 
    { 
     var temp = handler; 
     if (temp != null) 
     { 
      temp(sender, EventArgs.Empty); 
     } 
    } 
} 

Así que en su código que puede decir:

public bool IsDoorOpen 
{ 
    get { return isDoorOpen;} 
    private set 
    { 
     isDoorOpen = value; 
     DoorsChangeState.FireEvent(this); 
    } 
} 
+0

+1 ¡Eso hace una sintaxis muy agradable! – MPritchard