2012-12-22 36 views
5

ऐसा लगता है कि जब मैं किसी ऑब्जेक्ट क्लास की प्रतिनिधि विधि पर WeakReference कक्षा का उपयोग करता हूं, तो ऑब्जेक्ट क्लास जीसी द्वारा एकत्र की जाती है लेकिन WeakReference में रहने वाली इसकी एक और प्रतिलिपि अभी भी है?जीसी इकट्ठा नहीं होता है जब वीक रेफरेंस एक प्रतिनिधि का संदर्भ देता है?

मुझे शब्दों में व्याख्या करना मुश्किल लगता है। मैं एक उदाहरण दूंगा।

class TestObject 
{ 
    public string message = ""; 

    private delegate string deleg(); 

    public TestObject(string msg) 
    { 
     message = msg; 
    } 

    public Delegate GetMethod() 
    { 
     deleg tmp = this.TestMethod; 
     return tmp; 
    } 

    public string TestMethod() 
    { 
     return message; 
    } 

} 

अब, अपने मुख्य आवेदन में, मैं एक WeakReference के माध्यम से TestObject में विधि TestMethod का उल्लेख करने का प्रयास: मैं निम्नलिखित वस्तु वर्ग TestObject कहा जाता है। इरादा यह है कि TestObject जीसी द्वारा एकत्र किया जा सकता है जब सभी कठिन संदर्भ चले जाते हैं। यह कैसे अपने मुख्य आवेदन की तरह लग रहा है:

enter image description here

यहाँ अजीब बात है:

static void Main(string[] args) 
    { 
     var list = new List<WeakReference>(); 
     var obj = new TestObject("Hello 1"); 
     list.Add(new WeakReference(obj.GetMethod())); 
     Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke());  //Works fine 
     obj = null;  //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC 
     GC.Collect(); //Force GC 
     Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False")); 
     Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke()); 
     Console.ReadKey(); 
    } 

यह आउटपुट जब मैं ऊपर कोड चलाया जाता है। पहली पंक्ति पर, obj"Hello 1" प्रिंट कर सकता है क्योंकि इसे अभी शुरू किया गया था और objTestObject का संदर्भ रख रहा था। सब सही हैं। अगला, objnull पर obj = null के साथ सेट किया गया था और जीसी को एकत्र करने के लिए मजबूर होना पड़ा था। तो आउटपुट की दूसरी पंक्ति में, objtrue शून्य होने के लिए है। अंत में अंतिम पंक्ति पर, क्योंकि जीसी ने obj दूर एकत्र किया है, इसलिए मुझे उम्मीद है कि यह NullReferenceException फेंक दें या आउटपुट पर कुछ भी प्रिंट न करें। हालांकि, यह वास्तव में आउटपुट की पहली पंक्ति के समान चीज़ मुद्रित करता है! TestObject को इस बिंदु पर पहले से ही जीसी द्वारा एकत्र नहीं किया जाना चाहिए ?!

यह प्रश्न पूछता है कि जो पहले obj में आयोजित किया गया था, बाद में जीसी द्वारा एकत्र किया गया था या नहीं, जब मैं ओबीजे को शून्य पर सेट करता हूं।

यदि मैंने पूरे ऑब्जेक्ट को WeakReference, यानी new WeakReference(obj) में WeakReference में एक प्रतिनिधि के बजाय पारित किया था, तो यह पूरी तरह से काम करता।

दुर्भाग्यवश, मेरे कोड में, मुझे WeakReference एक प्रतिनिधि में प्रवेश करने की आवश्यकता है। मैं WeakReference सही ढंग से काम करने के लिए इतना है कि जीसी केवल एक प्रतिनिधि को संदर्भित होने से वस्तु दूर एकत्र कर सकते हैं कैसे हो सकती है?

उत्तर

5

मुझे लगता है कि समस्या अपने परीक्षण में है - ढांचे में नहीं। ऐसा प्रतीत होता है कि स्थानीय चर को शून्य पर सेट करने से आप जो भी उम्मीद कर रहे हैं वह नहीं करता है। हम पूरी तरह से स्थानीय चर छोड़ते हैं, हम 'के बाद' लाइन पर उम्मीद NullReferenceException मिलती है:

static void Main(string[] args) 
{ 
    var list = new List<WeakReference>(); 
    //var obj = new TestObject("Hello 1"); 
    list.Add(new WeakReference(new TestObject("Hello 1").GetMethod())); 
    Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke());  //Works fine 
    //obj = null;  //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC 
    GC.Collect(); //Force GC 
    //Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False")); 
    Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke()); 
    Console.ReadKey(); 
} 
0

वास्तव में अपने उदाहरण को छोड़कर WeakReference प्रतिनिधि को संदर्भित करता है के बाद से आप कुछ भी नहीं है की उम्मीद के रूप में चलेंगे,, इसलिए जीसी कर सकते हैं इसे इकट्ठा करें, भले ही आप "obj = null" पंक्ति को टिप्पणी करें!

This is my result

हो सकता है कि क्योंकि मैं एक अलग धागा (मुख्य थ्रेड को छोड़ कर) पर कोड चल रहा हूँ?