2010-05-07 20 views
5

Ich mache benutzerdefinierte Ereignisse für C# und manchmal funktioniert es nicht. passierenFrage über benutzerdefinierte Ereignisse

Dies ist, wie ich das Ereignis mache:

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

Und das sind die Ereignisdeklarationen:

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

Diese so lange funktioniert, wie es Methoden, um die Ereignisse gebunden sind, aber Wenn dies nicht der Fall ist, wird eine Ausnahme von null ref ausgelöst. Was mache ich falsch?

Antwort

10

Der empfohlene Weg, um ein Ereignis zu nennen, ist

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

Der Grund den Handler lokal für das Kopieren von Incase die Event-Handler-Änderungen auf einem anderen Thread ist, während Sie auf null sind zu überprüfen.

EDIT: Fand den Artikel über Race Conditions. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

+0

+1 nicht erkennen, die Threadsicherheitsprobleme und die Tatsache, dass Ereignisse unveränderlich sind. Danke für den Link. –

0

Wenn ein Ereignis nicht abonniert wird, wenn es ausgelöst wird, wird eine NullReferenceException ausgelöst. Das ist richtiges Verhalten, nicht etwas, was Sie falsch gemacht haben.

sollten Sie überprüfen:

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

Bevor ein Ereignis aufrufen Sie überprüfen müssen, ob das Ereignis null ist:

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

Wenn DoorsChangeState null ist, das heißt, es gibt keine Zuhörer an diesem Ereignis.

0

Sie müssen überprüfen, ob das Ereignis abonniert wurde.

Ich verwende dieses Standardformular, um alle meine Ereignisse zu werfen.

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

Ich weiß, diese Frage diskutiert wurde (und beantwortet) mehrmals hier auf SO. verwenden

irgendwo hier auch bekam ich folgende Erweiterungsmethoden dieses Muster leichter zu machen:

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

So in Ihrem Code können Sie sagen:

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

+1 Das macht eine sehr schöne Syntax! – MPritchard