Kie*_*ton 14 c# serialization multithreading thread-safety
引用这个问题的答案.
可以改写为:
    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);
        }
    }
那么为每次调用避免构造(和GC)一个新的BinaryFormatter?
这个代码路径非常频繁,因为它涉及我们的缓存层,我想尽可能轻量级.
谢谢.
Dar*_*rov 10
根据MSDN:
此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的.任何实例成员都不保证是线程安全的.
因此,您需要同步对Serialize/Deserialize方法的访问.
您是否每次都通过创建本地序列化程序实例来识别特定的性能问题?
更新:
我相信MSDN,因为即使在某些情况下我们可以验证实例成员可能是线程安全的,这并不意味着对于下一个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<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);
            }
    }
当然,另一种选择是使用Red Gate的Relfector.Net并查看二进制格式化程序的实现.阅读完代码后,您应该能够确定是否可以安全地进行交叉线程使用; 但是,达林是正确的,因为它可能在未来的版本中打破.
| 归档时间: | 
 | 
| 查看次数: | 5371 次 | 
| 最近记录: |