2009-09-21 20 views
12

Referenzieren this Antwort auf eine Frage.Sind BinaryFormatter serialisieren und deserialisieren threadsicher?

(und GC'ing)
private static BinaryFormatter formatter = new BinaryFormatter(); 

    public static T DeepClone<T>(this T a) 
    { 
     using(MemoryStream stream = new MemoryStream()) 
     { 
      formatter.Serialize(stream, a); 
      stream.Position = 0; 
      return (T)formatter.Deserialize(stream); 
     } 
    } 

So vermeidet den Aufbau eines neuen BinaryFormatter für jeden Anruf:

Kann dies als neu geschrieben werden?

Dieser Code-Pfad wird sehr häufig getroffen, da es unsere Caching-Ebene betrifft und ich möchte es so leicht wie möglich machen.

Danke.

+1

Ein klassisches Argument für unveränderlich;) –

Antwort

9

Nach MSDN:

Alle öffentlichen (Shared in Visual Basic) Member dieses Typs sind thread sicher. Alle Instanzmitglieder sind nicht garantiert Thread-sicher.

Sie müssen also den Zugriff auf Serialize/Deserialize-Methoden synchronisieren.

Haben Sie bestimmte Leistungsprobleme festgestellt, indem Sie jedes Mal eine lokale Serializer-Instanz erstellt haben?


UPDATE:

würde ich MSDN vertrauen, denn selbst wenn in einigen Fällen wir, dass die Instanzmitglieder Thread-sicher sein könnte, überprüfen kann, bedeutet dies nicht, dass mit dem nächsten Service Pack/update/Framework-Version dieses wird auch weiterhin so sein.

Suche mit Reflektor an BinaryFormatter Konstruktor:

public BinaryFormatter() 
{ 
    this.m_typeFormat = FormatterTypeStyle.TypesAlways; 
    this.m_securityLevel = TypeFilterLevel.Full; 
    this.m_surrogates = null; 
    this.m_context = new StreamingContext(StreamingContextStates.All); 
} 

Und Streaming Konstruktor:

public StreamingContext(StreamingContextStates state, object additional) 
{ 
    this.m_state = state; 
    this.m_additionalContext = additional; 
} 

Ganz ehrlich zuweisen 6 Eigenschaften (von denen die meisten enums sind) sollten blendend schnell sein. IMHO würde die meiste Zeit in Serialize/Deserialize-Methoden verbracht werden.

+0

Ja, das ist derzeit der heiße Pfad (wir haben gemessen). Es ist nicht das Ende der Welt, ein formatiert für jede Anfrage zu installieren, aber ich fragte mich, ob jemand wusste, ob es internes Caching etc. war. Ich war mir der Notiz auf MSDN bewusst, aber wie Sie wahrscheinlich wissen, sagt es für eine Menge Klassen, die tatsächlich Instanz Thread in der Realität sind sicher :) –

6

Sie können das Attribut [ThreadStatic] verwenden und initialisieren, wenn der Wert null ist. Dies funktioniert, wenn Sie Threads erneut verwenden.

[ThreadStatic] 
private static BinaryFormatter formatter = null; 

public static T DeepClone<T>(this T a) 
    { 
      if(formatter == null) formatter = new BinaryFormatter(); 
      using(MemoryStream stream = new MemoryStream()) 
      { 
        formatter.Serialize(stream, a); 
        stream.Position = 0; 
        return (T)formatter.Deserialize(stream); 
      } 
    } 

Natürlich ist die andere Option Relfector.Net von Red Gate zu verwenden und die Umsetzung des binären Formatter überprüfen. Nachdem Sie den Code gelesen haben, sollten Sie in der Lage sein zu entscheiden, ob der Cross-Thread-Einsatz sicher ist. Allerdings hat Darin insofern Recht, als es in einer zukünftigen Version brechen könnte.

Verwandte Themen