5

मान लीजिए कि मेरे पास लक्ष्य मजबूत संदर्भ का WeakReference है। मैं सूचित होना चाहता हूं कि लक्ष्य वस्तु स्वयं जीसी द्वारा एकत्र की जा रही है। क्या यह संभव है?क्या जीसी द्वारा एकत्रित वस्तुओं को हुक करना संभव है?

संपादित करें: अंतिमकर्ता/विनाशक को कोड जोड़ना यहां एक विकल्प नहीं है। मुझे ऐसा कुछ चाहिए जो क्लास कोड पर निर्भर न हो।

+0

मैं वहाँ जो इंगित करता है एक पते एकत्र की जा रही है किसी भी घटना को उठाया है पर विश्वास नहीं है यह अवधारणा कोड का सबूत इस प्रकार है। सबसे नज़दीकी चीज जो आप कोशिश कर सकते हैं वह संदर्भित प्रकार पर एक फाइनलाइज़र बना रहा है, हालांकि संग्रह होने से पहले एक अनिर्दिष्ट समय से पहले चलाया जाता है। मैं किसी को उत्तर देने के लिए समझदार हूं। –

+3

कचरा कलेक्टर इसे नष्ट कर देता है अगर आपके ऑब्जेक्ट के विनाशक को बुलाया जाता है। आप विनाशक कॉल में प्रतिक्रिया दे सकते हैं और उदाहरण के लिए एक स्वयं बनाया घटना भेज सकते हैं। –

+1

पुनरुत्थान के लिए एक नुस्खा की तरह लगता है। आप इसकी आवश्यकता क्यों है? – Ani

उत्तर

5

यह .NET 4.0 के तहत संभव है और ConditionalWeakTable<TKey, TValue> का उपयोग कर निम्नलिखित है। धन्यवाद this, और other साइट्स।

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

निम्न कोड के साथ परीक्षण किया गया:

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

Object.Finalize() विधि के बारे में क्या? क्या इसे अंतिम रूप देने पर नहीं बुलाया जाएगा?

+0

यह सही है। विनाशक पूरी तरह से 'ऑब्जेक्ट। फाइनलाइज()' कहता है, इसलिए इस विधि को ओवरराइड करना और यहां से सिग्नलिंग ऑब्जेक्ट कचरा एकत्र करने का सही समय देगा। –

+0

क्षमा करें, लेकिन मुझे कुछ और पारदर्शी चाहिए और कक्षा कोड पर निर्भर नहीं है। शायद यह संभव नहीं है। – ceztko

+1

यह तब तक काम करता है जब तक कि 'जीसी.SupressFinalize' को कॉल नहीं किया जाता है, जैसा कि आमतौर पर डिस्पोजेबल प्रकारों के मामले में होता है। इसके अतिरिक्त, सही समय जब कचरा संग्रह के दौरान अंतिमकरण निष्पादित होता है, वह अनिर्धारित होता है। –

0

आप कस्टम इंटरफ़ेस/कक्षा से विरासत में प्राप्त प्रत्येक कक्षा के लिए अंतिम रूप देने के लिए अवरोध का उपयोग कर सकते हैं। मुझे लगता है, यह वही है जो आप हासिल करने की कोशिश करना चाहते हैं, है ना? आप इसके लिए एकता का उपयोग कर सकते हैं। Here एक बहुत छोटा उदाहरण है जो एकता के साथ हस्तक्षेप कैसे करें।

+0

सही (वास्तव में, यह एक इंटरफ़ेस है, इसलिए यह समझाया गया है कि मैं बेस क्लास फ़ाइनलाइज़र में कोड क्यों नहीं लिख सकता)। क्या एकता कुछ है जो .NET 3.5 में अंतर्निहित है? – ceztko

+0

[यहां] के अनुसार (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=15104), यह .NET 3.5 SP1 का भी समर्थन करता है। लेकिन, मैंने इसे .NET 4.0 में उपयोग किया है। इसके अलावा, वेब के आसपास अन्य आईओसी पुस्तकालय भी हैं। लेकिन, मैंने पाया है कि एकता अधिक मजबूत समाधान है। –

+0

मैं इसे देख रहा हूँ। यह एक अच्छा और आसान समाधान हो सकता है। – ceztko