5

Giả sử tôi có một số WeakReference của tham chiếu mạnh mẽ mục tiêu. Tôi muốn được thông báo khi chính đối tượng mục tiêu đang được GC thu thập. Có thể không?Có thể móc các vật thể được GC thu thập không?

EDIT: Thêm mã vào finalizer/destructor không phải là một tùy chọn ở đây. Tôi cần cái gì đó không phụ thuộc vào mã lớp.

+0

Tôi không tin có bất kỳ sự kiện lớn lên mà chỉ một địa chỉ đang được thu thập. Điều gần nhất bạn có thể thử là tạo một Trình hoàn tất trên loại đang được tham chiếu, mặc dù chúng chạy trước một thời gian không xác định trước khi bộ sưu tập xảy ra. Tôi mong ai đó thông minh hơn đưa ra câu trả lời. –

+3

Các destructor của đối tượng của bạn được gọi là nếu thu gom rác phá hủy nó. Bạn có thể phản ứng trong cuộc gọi destructor và gửi một sự kiện tự tạo ví dụ. –

+1

Âm thanh như một công thức để phục sinh. Tại sao bạn cần điều này? – Ani

Trả lời

5

Có thể theo .NET 4.0 và sau bằng cách sử dụng ConditionalWeakTable<TKey, TValue>. Cảm ơn thisother trang web. Nó sau chứng minh mã khái niệm:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Runtime.CompilerServices; 

namespace Test 
{ 
    public static class GCInterceptor 
    { 
     private static ConditionalWeakTable<object, CallbackRef> _table; 

     static GCInterceptor() 
     { 
      _table = new ConditionalWeakTable<object, CallbackRef>(); 
     } 

     public static void RegisterGCEvent(this object obj, Action<int> action) 
     { 
      CallbackRef callbackRef; 
      bool found = _table.TryGetValue(obj, out callbackRef); 
      if (found) 
      { 
       callbackRef.Collected += action; 
       return; 
      } 

      int hashCode = RuntimeHelpers.GetHashCode(obj); 
      callbackRef = new CallbackRef(hashCode); 
      callbackRef.Collected += action; 
      _table.Add(obj, callbackRef); 
     } 

     public static void DeregisterGCEvent(this object obj, Action<int> action) 
     { 
      CallbackRef callbackRef; 
      bool found = _table.TryGetValue(obj, out callbackRef); 
      if (!found) 
       throw new Exception("No events registered"); 

      callbackRef.Collected -= action; 
     } 

     private class CallbackRef 
     { 
      private int _hashCode; 
      public event Action<int> Collected; 

      public CallbackRef(int hashCode) 
      { 
       _hashCode = hashCode; 
      } 

      ~CallbackRef() 
      { 
       Action<int> handle = Collected; 
       if (handle != null) 
        handle(_hashCode); 
      } 
     } 
    } 
} 

Thử nghiệm với đoạn mã sau:

public partial class Form1 : Form 
{ 
    private object _obj; 

    public Form1() 
    { 
     InitializeComponent(); 

     _obj = new object(); 

     _obj.RegisterGCEvent(delegate(int hashCode) 
     { 
      MessageBox.Show("Object with hash code " + hashCode + " recently collected"); 
     }); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     _obj = null; 
     GC.Collect(); 
    } 
} 
2

Còn phương pháp Object.Finalize() thì sao? Sẽ không được gọi khi hoàn thành?

+0

Điều này là chính xác. Trình phá hủy ngầm gọi 'Object.Finalize()', để ghi đè phương thức này và tín hiệu từ đây sẽ cho chính xác thời gian đối tượng là rác được thu thập. –

+0

Xin lỗi, nhưng tôi cần một cái gì đó minh bạch hơn và không phụ thuộc vào mã lớp. Có lẽ nó là không thể. – ceztko

+1

Tính năng này hoạt động trừ khi có cuộc gọi đến 'GC.SupressFinalize' được thực hiện, như thường là trường hợp đối với các loại Có thể loại bỏ. Ngoài ra, thời gian chính xác khi trình hoàn thành thực thi trong khi thu thập rác là không xác định. –

0

Bạn có thể sử dụng tính năng chặn để bắt Finalize cho mỗi lớp được kế thừa từ giao diện/lớp tùy chỉnh. Tôi nghĩ, đây là những gì bạn muốn đạt được, đúng không? Bạn có thể sử dụng Unity cho điều đó. Here là một ví dụ rất ngắn về cách đánh chặn với Unity.

+0

Đúng (thực ra, nó là một giao diện, do đó, nó giải thích lý do tại sao tôi không thể viết mã trong finalizer lớp cơ sở). Unity có được tích hợp trong .NET 3.5 không? – ceztko

+0

Theo [tại đây] (http://www.microsoft.com/download/en/details.aspx?displaylang=vi&id=15104), nó cũng hỗ trợ .NET 3.5 SP1. Nhưng, tôi đã sử dụng nó trong .NET 4.0. Ngoài ra, còn có các thư viện IoC khác trên web. Nhưng, tôi thấy Unity là giải pháp mạnh mẽ hơn. –

+0

Tôi đang xem xét nó. Nó có thể là một giải pháp tốt và dễ dàng. – ceztko

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