BinaryFormatter是否对线程安全进行序列化和反序列化?

引用这个问题的答案。

可以改写为:

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

那么为每次调用避免构造(和GC)一个新的BinaryFormatter?

这个代码路径非常频繁,因为它涉及我们的缓存层,我想尽可能轻量级。

谢谢。

根据MSDN :

此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。 任何实例成员都不保证是线程安全的。

因此,您需要同步对Serialize / Deserialize方法的访问。

您是否每次都通过创建本地序列化程序实例来识别特定的性能问题?


更新:

我相信MSDN,因为即使在某些情况下我们可以validation实例成员可能是线程安全的,这并不意味着对于下一个Service Pack / update / framework版本,这将继续如此。

在BinaryFormatter构造函数中使用Reflector查找:

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

和StreamingContext构造函数:

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

坦率地说,分配6个属性(大多数是enums )应该非常快。 恕我直言,大部分时间都花在序列化/反序列化方法上。

您可以使用[ThreadStatic]属性并初始化value是否为null。 假设您重用线程,这将有效。

 [ThreadStatic] private static BinaryFormatter formatter = null; public static T DeepClone(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); } } 

当然,另一种选择是使用Red Gate的Relfector.Net并查看二进制格式化程序的实现。 阅读完代码后,您应该能够确定是否可以安全地进行交叉线程使用; 但是,达林是正确的,因为它可能在未来的版本中破裂。