2009-09-21 3 views
12

Ссылка this ответ на вопрос.Являются ли двоичные файлы сериализованными и десериализованными потоками безопасными?

Может ли это быть переписано в виде:

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'ing) новый BinaryFormatter для каждого вызова?

Этот путь кода очень сильно ударяется, поскольку он включает в себя наш слой кеширования, и я хотел бы сделать его максимально легким.

Спасибо.

+1

Классический аргумент для неизменяемого;) –

ответ

9

По MSDN:

Любые открытые статический (Shared в визуальных Basic) члены этого типа являются поточно безопасны. Любые члены экземпляра не являются гарантированно надежными потоками.

Таким образом, вам необходимо синхронизировать доступ к методам сериализации/десериализации.

Вы определили конкретные проблемы с производительностью, создавая экземпляр локального сериализатора каждый раз?


UPDATE:

Я доверяю MSDN, потому что даже если в некоторых случаях мы можем убедиться, что члены экземпляра может быть Потокобезопасным это не означает, что со следующим пакетом обновления/обновление/рамкой версия этого будет продолжаться.

Глядя с отражателем в BinaryFormatter конструктору:

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) должны быть ослепительно быстро. ИМХО большую часть времени будет потрачено на методы Serialize/Deserialize.

+0

Да, в настоящее время это горячий путь (мы измерили). Это не конец света, чтобы стимулировать отформатированный для каждого запроса, но я задавался вопросом, знал ли кто-нибудь о внутреннем кэшировании и т. Д. Я знал об уведомлении в MSDN, но, как вы, наверное, знаете, он говорит, что для многих классы, которые на самом деле являются потоками потоков в действительности :) –

6

Вы можете использовать атрибут [ThreadStatic] и инициализировать, если значение равно 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); 
      } 
    } 

Конечно, другой вариант заключается в использовании Relfector.Net от Red Gate и обзор осуществления бинарного форматтера. После прочтения кода вы сможете решить, безопасно ли использование поперечной резьбы; Тем не менее, Дарин прав в том, что он может разразиться в будущем выпуске.

Смежные вопросы