2011-01-06 7 views
6

Ist diese Erweiterungsmethode threadsicher?Ist die Erweiterungsmethode threadsicher?

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

oder muss ich es ändern?

+0

Design und Implementierung Details von Ereignissen in Bezug auf Threading http://StackOverflow.com/Questions/786383/c-Events-and-Thread-Safety – user44298

Antwort

9

Sie haben ein interessantes Loop-Loch gefunden, es hat alle überrascht. Nein, es ist nicht threadsicher.

Während es aussieht wie der EventHandler <> Verweis wird über die Methode Argument kopiert, das ist nicht, was zur Laufzeit passiert. Erweiterungsmethoden können wie eine normale Instanzmethode inline ausgeführt werden. In der Tat ist es extrem wahrscheinlich inline, da es so klein ist. Es gibt keine Kopie, du musst selbst eins machen.

+1

Ich bin nicht sicher, dass Sie richtig sind. Dies würde nur gelten, wenn die aufrufende Funktion die Methode auf einen Wert aufruft, der von einem anderen Thread geändert werden könnte (z. B. ein Klassenfeld anstelle einer lokalen Variablen). Ich weiß nicht, ob der JIT in diesem Fall einen solchen Anruf in die Leitung bringen würde. – tster

+0

Dies ist jedoch ein sehr interessantes Thema. Ich wünschte, ich wäre nicht bei der Arbeit und hätte die Zeit gehabt, mehr zu erfahren. – tster

+1

Nun, darum geht es beim Null-Test im Ereignis-Code. –

7

Keine der beiden Versionen ist threadsafe, je nachdem, was Sie unter "threadsafe" verstehen. Betrachten Sie Ihre zweite Version:

var h = handler;   
    if (h!= null) 
     h(sender, args); 

"Handler" ist eine Kopie eines Feldes, das einen unveränderlichen Delegaten enthält. Angenommen, das Feld wird nach der Nullprüfung in einem anderen Thread zu "null" mutiert. Ihr Code stürzt in diesem Fall nicht ab, weil Sie eine Kopie des ursprünglichen Nicht-Null-Werts erstellt haben. Aber nur nicht Absturz macht nicht das Programm Thread sicher. Ein Programm, das nicht abstürzt, aber immer noch die falschen Ergebnisse liefert, ist immer noch nicht threadsicher.

Angenommen, der andere Thread hat das Ereignisfeld auf null gesetzt, hat auch einen Zustand mutiert, in dem der vorherige Inhalt korrekt ausgeführt werden musste. Sie werden jetzt einen Event-Handler ausführen, der vom Zustand abhängt, der gerade in einem anderen Thread mutiert wurde; Sie führen einen veralteten Event-Handler.

Es gibt keine einfache Möglichkeit, sich vor diesem Problem zu schützen; Wenn das die Situation ist, in der Sie sich befinden, müssen Sie Ihre Threading-Logik sehr sorgfältig entwerfen, um mit der Situation fertig zu werden.