2013-02-22 18 views
7
private void NotifyFreeChannelsChanged() //1. 
{ 
    if (FreeChannelsChanged != null) 
    { 
     FreeChannelsChanged(this, null); 
    } 
} 

private void NotifyFreeChannelsChanged() //2. 
{ 
    NotifyCollectionChangedEventHandler h = FreeChannelsChanged ; 
    if (h != null) 
     h(this, e); 
} 

aus denen, die besser ist und warum. oder es ist nur ein Extra-Check. kein großer Unterschied.Welches ist der bessere Ansatz zum Aufrufen eines Ereignisdelegaten?

+0

http://stackoverflow.com/questions/3668953/raise-event-thread-safely-best-practice?rq=1 –

+1

Option # 2 mit implizit typisierter Variable. Ich möchte hinzufügen, dass, wenn Leistung kein Problem ist, sich nicht darum kümmern. Lieber Lesbarkeit und Wartbarkeit bevorzugen. – jay

Antwort

6

"Besser"? Nun, enthält keine (spezifische) Race Condition, tut man. MultiCastDelegate-Typen sind unveränderlich und verwenden Werttyp-Semantik auf alle relevanten Arten (sie sind sind Referenztypen jedoch siehe this und, noch wichtiger, this), deshalb weisen Sie sie zuerst zu und dann überprüfen. Das Problem ist das:

// this evaluates to true... 
if(SomeEvent != null) 
{ 
    // ...but before this line executes, the last 
    // subscriber detached, and now SomeEvent is null. Oops. 
    SomeEvent(this, e); 
} 

Sie sollten gefragt haben "warum sollte jemand Beispiel # 2 verwenden?"


Als beiseite, das ist ein großartiger Ort, eine implizit typisierte Variablen zu verwenden (var). Diese Delegattypnamen werden lang ...

Interessant ist auch, dass eine Race-Bedingung immer noch existiert, es ist nur subtiler. Was passiert, wenn ein Teilnehmer nach der Zuweisung entfernt wird? Nun, es wird immer noch angerufen werden, aber es gibt wirklich nichts (ich weiß), dass Sie es tun können.

0

Die zweite ist, gegen einen möglichen threading-Fehler zu schützen, bei dem ein Kontextwechsel zwischen dem Null-Check und der Ereignisauslösung in Code-Schnipsel 1 stattfindet. Ein anderer Thread kann ihn dazwischen auf null setzen.

Wenn Ihre Methode also nicht zum Multithreading neigt, können Sie das einfachere Snippet verwenden.

+0

Ich entscheide mich einfach, die Race Condition alle zusammen zu vermeiden, egal wie ich erwarte, dass der Code aufgerufen wird, wenn ich ihn schreibe. Es kostet nichts. –

1

Die zweite eignet sich sehr gut für eine Reihe von Erweiterungsmethoden, die wir verwenden, wobei der EventHandler das Ziel der Methode ist.

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

// And then... 
TheEvent.Raise(this); 

Soweit ich weiß, ist die Tatsache, dass Sie die Prozedur eine Methode übergeben gibt Ihnen die lokale Kopie eines Race-Bedingung zu vermeiden.

Verwandte Themen