Frage

Ich habe gerade eine Seite gelesen Veranstaltungen Auf MSDN, und ich stieß auf einen Ausschnitt von Beispielcode, der mich verwirrt.

Der fragliche Code ist Folgendes:

// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

Ich verstehe die Absichten des Codes, aber ich sehe nicht, wie diese bestimmte Zeile eine Kopie von irgendetwas erstellt. Alles was es tut, ist das Kopieren der Hinweis; Es macht nicht wirklich eine tiefe Kopie der Delegierteninstanz. Zu diesem Zweck verhindert es also überhaupt nicht die Rennbedingung.

Vermisse ich hier etwas Offensichtliches?

War es hilfreich?

Lösung

Die Delegierten sind unveränderlich, so dass sich die in diesem Code erhaltene Referenz nicht ändert. Wenn ein Benutzer nach dem Null -Check abonniert oder sich abschließt, wird ein neuer Delegierter erstellt und auf das Ereignis eingestellt. Da Sie jedoch einen Verweis auf ein völlig anderes Objekt haben und dies aufrufen, müssen Sie sich keine Sorgen darüber machen, dass es null ist.

Andere Tipps

Du hast Recht; Es kopiert die Referenz.

Delegierte sind jedoch unveränderlich; Wenn Sie einem Ereignis einen Handler hinzufügen, wird ein neuer Delegierter erstellt, der den aktuellen Handler mit dem neuen kombiniert und dem Feld dann zugeordnet ist.

Die Delegierteinstanz, auf die sich das Feld bezieht, kann sich nicht ändern, sodass es den Rennbedingung vermeidet.

Eric Lippert Bereits in einem sehr detaillierten behandelten Post.

Dies ist auch von msdn ..

"Die Aufrufliste eines Delegiertens ist ein geordneter Satz von Delegierten, in denen jedes Element des Die Liste ruft genau eine der vom Delegierten dargestellten Methoden auf. Eine Aufrufliste kann doppelte Methoden enthalten. Während eines Aufrufs werden Methoden in der Reihenfolge aufgerufen, in der sie in der Aufrufliste angezeigt werden. Ein Delegierter versucht, jede Methode in seiner Aufrufliste aufzurufen. Duplikate werden einmal für jedes Mal aufgerufen, wenn sie in der Aufrufliste angezeigt werden. Delegierte sind unveränderlich; Nach dem Erstellen ändert sich die Aufrufliste eines Delegierten nicht."

if (whatever != null) whatever(); Sieht so aus, als ob es sich sicherstellt whatever ist niemals null, wenn whatever() wird aufgerufen, aber es sorgt nicht wirklich in einem Thread -Szenario. Ein anderer Thread kann einstellen whatever = null zwischen dem Scheck und dem Anruf.

Foo temp = whatever;
if (temp != null) temp();

Dieser Code beseitigt die Möglichkeit der Null -Dereferenz, seitdem temp ist ein lokaler und wird daher niemals durch einen anderen Thread geändert. Es verhindert also einen Rassenzustand. Es verhindert jedoch nicht alle relevanten Rennbedingungen. Eric Lippert hat a aufwändiger Diskussion einiger anderer Probleme mit dem Code.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top