2009-09-21 33 views
12

Tham khảo this trả lời cho một câu hỏi.BinaryFormatter Serialize và Deserialize thread có an toàn không?

này có thể được viết lại như sau:

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); 
     } 
    } 

Vì vậy, tránh xây dựng (và GC'ing) một BinaryFormatter mới cho mỗi cuộc gọi?

Đường dẫn mã này đang được truy cập rất thường xuyên vì nó liên quan đến lớp bộ nhớ đệm của chúng tôi và tôi muốn làm cho nó nhẹ nhất có thể.

Cảm ơn.

+1

Một đối số cổ điển cho bất biến;) –

Trả lời

9

Theo MSDN:

Bất kỳ public static (Shared trong Visual Basic ) thành viên thuộc loại này là thread an toàn. Bất kỳ thành viên cá thể nào không phải là được đảm bảo là chuỗi an toàn.

Vì vậy, bạn cần phải đồng bộ hóa quyền truy cập vào các phương thức Serialize/Deserialize.

Bạn đã xác định các vấn đề hiệu suất cụ thể bằng cách tạo một cá thể trình nối tiếp cục bộ mỗi lần?


UPDATE:

tôi sẽ tin tưởng MSDN vì ngay cả khi trong một số trường hợp chúng ta có thể xác minh rằng các thành viên dụ có thể là chủ đề an toàn này không có nghĩa rằng với dịch vụ tiếp theo gói/cập nhật/phiên bản khung này sẽ tiếp tục là trường hợp.

Nhìn với Reflector tại BinaryFormatter constructor:

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

Và StreamingContext constructor:

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

Khá thẳng thắn gán 6 tài sản (hầu hết trong số đó là enums) nên blindingly nhanh. IMHO hầu hết thời gian sẽ được sử dụng trong các phương thức Serialize/Deserialize.

+0

Có đó hiện là đường dẫn nóng (chúng tôi đã đo). Nó không phải là kết thúc của thế giới để instanciate một định dạng cho mỗi yêu cầu, nhưng tôi tự hỏi nếu có ai biết nếu nó đã làm bộ nhớ đệm nội bộ vv Tôi đã nhận thức được thông báo trên MSDN, nhưng như bạn có thể biết, nó nói rằng đối với rất nhiều các lớp học thực sự là chủ đề an toàn trong thực tế :) –

6

Bạn có thể sử dụng thuộc tính [ThreadStatic] và khởi tạo nếu giá trị bằng không. Điều này sẽ làm việc giả sử các chủ đề sử dụng lại của bạn.

[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); 
      } 
    } 

Tất nhiên, tùy chọn khác là sử dụng Relfector.Net từ Cổng đỏ và xem xét việc triển khai trình định dạng nhị phân. Sau khi đọc mã, bạn sẽ có thể quyết định xem nó có an toàn cho việc sử dụng chuỗi chéo hay không; Tuy nhiên, Darin là chính xác ở chỗ nó có thể phá vỡ trong một phiên bản tương lai.

Các vấn đề liên quan