2011-12-29 51 views
10

của Microsoft Là một C++ lập trình viên dày dạn cố gắng để làm quen với .NET, có một chi tiết thực hiện tại của Microsoft WeakReference "Target" tài sản đó là bugging tôi ...Đang cố gắng để hiểu được thực hiện WeakReference

public class WeakReference : ISerializable 
{ 
    internal IntPtr m_handle; 
    internal bool m_IsLongReference; 
       ... 
    public virtual object Target 
    { 
     [SecuritySafeCritical] 
     get 
     { 
      IntPtr handle = this.m_handle; 
      if (IntPtr.Zero == handle) 
      { 
       return null; 
      } 
      object result = GCHandle.InternalGet(handle); 
      if (!(this.m_handle == IntPtr.Zero)) 
      { 
       return result; 
      } 
      return null; 
     } 
     [SecuritySafeCritical] 
     set 
     { 
      IntPtr handle = this.m_handle; 
      if (handle == IntPtr.Zero) 
      { 
       throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); 
      } 
      object oldValue = GCHandle.InternalGet(handle); 
      handle = this.m_handle; 
      if (handle == IntPtr.Zero) 
      { 
       throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); 
      } 
      GCHandle.InternalCompareExchange(handle, value, oldValue, false); 
      GC.KeepAlive(this); 
     } 
    } 
    ... 
     } 

Điều đó là bugging tôi là điều này - tại sao họ kiểm tra tính hợp lệ của m_handle hai lần? Đặc biệt trong phương pháp 'set' - việc sử dụng GC.KeepAlive ở cuối phương thức nên giữ cho WeakReference không bị thu gom rác, và do đó giữ cho tay cầm khác không phải - đúng không?

Và trong trường hợp 'get' - khi chúng tôi đã thực sự truy lục tham chiếu đến đích thông qua InternalGet, tại sao lại phải kiểm tra lại giá trị m_handle ban đầu? Tất cả những gì tôi có thể nghĩ là có lẽ họ đang cố gắng bảo vệ chống lại WeakReference đang được xử lý và hoàn thành trong hoặc sau InternalGet - nhưng chắc chắn, nó cũng không thể được xử lý và hoàn thành trước khi chúng ta quay lại để trả lại đồ vật? Tôi chỉ không thể đưa ra w/một lời giải thích hợp lệ là tại sao kiểm tra hai lần này là cần thiết ở đây ...

+0

Tại sao bạn quan tâm đến việc triển khai nhiều như vậy? Và đây có phải là mã được cấp phép thực sự của Microsoft mà bạn đang đăng, hay là của Mono? – Dykam

+0

+1 Câu hỏi hay. Dường như không có ý nghĩa nhiều trong một trong hai người truy cập. – Groo

+7

@Dykam Đọc mã là một cách tuyệt vời để tìm hiểu và xử lý mã thư viện là "ma thuật" là một cách tuyệt vời để không học hỏi và phát triển mê tín dị đoan. Ngoài ra, tôi ghét phải nghĩ rằng đoạn mã này không bị sử dụng hợp lý ngay cả khi nó có bản quyền. –

Trả lời

8

Tất cả tôi có thể nghĩ là có lẽ họ đang cố gắng để bảo vệ chống lại các WeakReference được xử lý và đã hoàn thành trong hoặc sau InternalGet

Điều đó hoàn toàn chính xác.

nhưng chắc chắn, nó cũng không được xử lý và hoàn thành trước khi chúng tôi quay lại để trả lại đối tượng?

Không, bởi vì tại thời điểm đó, một con trỏ mạnh phải được tạo cho đối tượng. InternalGet trả về một con trỏ mạnh, và nếu con trỏ mạnh đó, được lưu trữ trong oldValue, là đối tượng, bây giờ đối tượng không còn có thể được thu hồi bởi bộ gom rác.

+0

Cuộc gọi đến 'InternalGet' không tạo ra con trỏ mạnh mẽ, nhưng bất kỳ việc thực hiện nào nó có. –

+0

@TomislavMarkovski Nó có hiệu quả, vì nó tạo ra một gốc cho đối tượng được tham chiếu trong 'GCHandle' (giá trị trả về). Khi bạn lưu trữ giá trị trả về (oldValue), bạn đã có một tham chiếu GC bắt nguồn, vì vậy đối tượng không còn đủ điều kiện cho GC. –

+0

Cảm ơn! Tôi vẫn chưa thấy logic. Điều duy nhất có thể bằng không trong xử lý nội bộ là trình hoàn thiện - vì vậy cách duy nhất mà xử lý có thể thay đổi trong suốt cuộc gọi này là nếu trình kết thúc của WeakReference được gọi trên đường đi. Hãy nói rằng tôi có một trong những "zombie" WeakReference của WeakReference này - vì vậy tôi gọi "get" trên WeakReference này sau khi finalizer của nó đã được lên kế hoạch. Tuy nhiên - cách duy nhất mà kiểm tra thứ hai trên tay cầm có thể tạo ra sự khác biệt là nếu trình kết thúc của WR được gọi ở đâu đó giữa kiểm tra đầu tiên và thứ hai. – Kevin

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