2010-08-13 12 views
9

मैं ऑब्जेक्ट्स पर कचरा संग्रहण प्रक्रिया के बारे में उलझन में हूं।ऑब्जेक्ट संदर्भों पर कचरा संग्रह कैसे काम करता है?

object A = new object(); 
object B = A;   
B.Dispose(); 

एक निपटान बुला तक चर बी पर केवल, निर्मित ऑब्जेक्ट कचरा एकत्र नहीं किया जाएगा वस्तु के रूप में अभी भी ए द्वारा संदर्भित है

अब करता है निम्नलिखित कोड काम से ऊपर के रूप में ही?

public static image Test1() 
{ 
    Bitmap A = new Bitmap(); 
    return A; 
} 

अब मैं इस स्थिर कार्य को किसी अन्य विधि से कॉल करता हूं।

public void TestB() 
{ 
    Bitmap B = Test1(); 
    B.Dispose(); 
} 

स्थैतिक फ़ंक्शन टेस्ट 1 ने बिटमैप ऑब्जेक्ट का संदर्भ दिया। संदर्भ को अन्य वैरिएबल बी में सहेजा गया है बी पर निपटान करके, बी और ऑब्जेक्ट के बीच कनेक्शन खो गया है लेकिन टेस्ट 1 से पारित संदर्भ के साथ क्या होता है। क्या यह तब तक सक्रिय रहेगा जब तक कि टेस्टबी का कार्य पूरा नहीं हो जाता?

क्या स्थिर कार्य से तुरंत संदर्भित करने के लिए कोई तरीका है?

+2

कचरा संग्रह संदर्भ गणना नहीं है। –

+0

कचरा संग्रह का पूरा बिंदु यह है कि आपको इस बात की परवाह नहीं है कि स्मृति कब जारी की जा रही है या नहीं। सिद्धांत रूप में, स्मृति के विशाल भंडार वाले सिस्टम पर, कचरा संग्रह _verver_ हो सकता है, बस क्योंकि यह समाप्त होने पर सब कुछ साफ होने के लिए और अधिक कुशल होगा। –

उत्तर

15

मैं बंद हो सकता हूं, लेकिन आपको Dispose और कचरा संग्रह की गलतफहमी दिखाई देती है। एक ऑब्जेक्ट कचरा होगा जब एक बार सभी संदर्भों को एक गैर-निर्धारक तरीके से चलाया जाता है। निपटान आमतौर पर अप्रबंधित संसाधनों से छुटकारा पाता है, इसलिए वस्तु कचरा इकट्ठा करने के लिए तैयार है। आपके पहले उदाहरण में, आपने ऑब्जेक्ट को विस्थापित कर दिया, सैद्धांतिक रूप से इसे अनुपयोगी बना दिया, लेकिन यह अभी भी ढेर पर मौजूद है और आपके पास अभी भी ए और बी दोनों का संदर्भ है। एक बार जब वे दायरे से बाहर निकल जाएंगे, तो कचरा कलेक्टर उस स्मृति को पुनः प्राप्त कर सकता है , लेकिन हमेशा नहीं। उदाहरण 2 में, एक बिटमैप ए ढेर पर रखा जाता है, फिर आप इसका संदर्भ वापस लेते हैं, और उस संदर्भ में बी सेट करते हैं। फिर आप इसे निपटान करते हैं और बी गुंजाइश से बाहर चला जाता है। उस बिंदु पर इसका कोई और संदर्भ मौजूद नहीं है, और बाद में यह कचरा इकट्ठा किया जाएगा।

+0

आपकी प्रतिक्रिया के लिए धन्यवाद। मुझे अपना प्रश्न और स्पष्ट करना चाहिए था। मुझे पता है कि निपटान() को कॉल करके, जीसी तुरंत स्मृति को मुक्त नहीं करेगा, लेकिन यह ऑब्जेक्ट को संदर्भित कतार से संदर्भ को हटा देगा ताकि ऑब्जेक्ट अगले जनरल पर नहीं चलेगा। दूसरे उदाहरण में हम निपटान कैसे करते हैं उपयोग के तुरंत बाद समारोह द्वारा पारित संदर्भ पर? यदि हम स्थिर कार्य द्वारा पारित संदर्भ का निपटान नहीं कर सकते हैं, तो यह अगले जनरल के पास जाएगा और संसाधन को मुक्त करने में और देरी होगी। – kishore

+1

@ किशोर: जब आप संदर्भ का निपटान करते हैं, तो यह बहुत भ्रमित है कि आपका क्या मतलब है। संदर्भ कम से कम इस मामले में ढेर पर वस्तु के ढेर पर एक सूचक है। आप ढेर पर उदाहरण में अप्रबंधित संसाधनों का निपटान करते हैं। –

+0

भ्रम के लिए खेद है। तो क्या फ़ंक्शन द्वारा पारित संदर्भ को हटाने या साफ़ करने का कोई तरीका है ताकि यह ढेर पर ऑब्जेक्ट को इंगित न करे? – kishore

15

Dispose कचरा इकट्ठा नहीं करता है। आप स्पष्ट रूप से कचरा एक विशेष वस्तु एकत्र नहीं कर सकते हैं। आप GC.Collect() पर कॉल कर सकते हैं जो अनुरोध करता है कि कचरा कलेक्टर चलता है, लेकिन यह वही नहीं है। कॉलिंग Dispose ऑब्जेक्ट को एक विशेष चर से "डिस्कनेक्ट" भी नहीं करता है, वास्तव में ... जबकि वह चर रहता है (पिछली बार जब तक यह पता लगाया जा सके कि यह कभी भी पढ़ा जाएगा) यह ऑब्जेक्ट को रोक देगा कचरा इकट्ठा किया जा रहा है।

एक ऑब्जेक्ट कचरा नहीं होगा जब तक कि इसे किसी भी चीज़ द्वारा संदर्भित नहीं किया जाता है। माना जाता है कि यह कुछ चरम मामलों में आपके विचार से पहले हो सकता है, लेकिन आपको शायद ही कभी उन लोगों के बारे में चिंता करने की ज़रूरत है।

यह जानना उचित है कि Dispose और कचरा संग्रह बहुत अलग चीजें हैं। अप्रबंधित संसाधन (नेटवर्क कनेक्शन इत्यादि) जारी करने के लिए आप Dispose पर कॉल करें। कचरा संग्रह पूरी तरह से स्मृति जारी करने के लिए है। माना जाता है कि कचरा संग्रह अंतिम रूप से जा सकता है जो अप्रबंधित संसाधनों को अंतिम उपाय के रूप में जारी कर सकता है, लेकिन अधिकांश समय आपको अप्रबंधित संसाधनों का स्पष्ट रूप से निपटान करना चाहिए।

+0

एक परिशिष्ट के रूप में, आपको कभी भी अंतिम बार पर भरोसा नहीं करना चाहिए, क्योंकि वे कभी नहीं चल सकते हैं। सबसे अच्छा, वे "अंतिम रिसॉर्ट्स" हो सकते हैं जो संसाधनों को साफ करने की कोशिश करेंगे यदि कार्यक्रम स्पष्ट रूप से उनका निपटान करने के लिए भूल गया है। – siride

3

निपटान() कचरा संग्रह के साथ कुछ भी करने के लिए नहीं है। यह सब संसाधनों की निर्धारिक रिलीज की अनुमति देता है, लेकिन आपको इसे स्पष्ट रूप से कॉल करना होगा। जिस वस्तु को आप इसे कॉल करते हैं उसे कचरा नहीं मिलता है जब आप निपटान() कहते हैं। यह कचरा संग्रह के लिए योग्य होगा जब इसके सभी संदर्भ चले गए हैं।

5

ऐसा होता है कि Raymond Chen ने अभी .NET कचरा संग्रह के पहलुओं का वर्णन करने वाले ब्लॉग पोस्टों की एक श्रृंखला लिखी है। This post सबसे अधिक सीधे आपके प्रश्न से संबंधित है (जब वस्तुओं को कचरा इकट्ठा किया जाता है?)।

+0

मैं हर साल सीएलआर सप्ताह की प्रतीक्षा करता हूं :) –

+0

मैं एक लिंक पोस्ट करने जा रहा था, लेकिन मैं आज सुबह थोड़ा आलसी महसूस कर रहा था। जीसी से संबंधित विषयों पर उनके कुछ महान पद हैं। – siride

+0

पोस्ट साझा करने के लिए धन्यवाद। – kishore

1

स्टार्टर्स के लिए ठीक है निपटान करें! = कचरा एकत्रित किया गया। आप निपटान को कॉल कर सकते हैं और कभी भी कचरा एकत्र नहीं किया जा सकता है, क्योंकि "डिसप्स्ड ऑब्जेक्ट" में अभी भी इसका संदर्भ हो सकता है। सीजी चलाने से पहले ऑब्जेक्ट को "टिडी अप" करने के लिए प्रयोग किया जाता है (बंद ओपन डीबी कनेक्शन, या फाइल कनेक्शन इत्यादि)।

object A = new object(); 
object B = A;   
B.Dispose(); 

इस उदाहरण में B.Dispose, एक पर निपटाने विधि बुला रहा है क्योंकि बी चर ए में वस्तु संदर्भित कर रहा है न तो CGD हो जाएगा, क्योंकि वे क्षेत्र से बाहर अभी तक गिर नहीं किया है।

public static image Test1() 
{ 
    Bitmap A = new Bitmap(); 
    return A; 
} 

यहाँ क्या हो रहा है कि आप वस्तु एक पैदा कर रहे हैं और यह लौटने, इसलिए जब आप Test1 छोड़ देते हैं, एक सबसे अधिक संभावना बुला विधि में एक और चर द्वारा संदर्भित किया जा रहा है। इसका मतलब यह है कि भले ही आपने विधि छोड़ी हो, फिर भी ए रूट (सबसे अधिक संभावना) है और जब तक कॉलिंग विधि नहीं की जाती तब तक CG'd नहीं किया जाएगा।

public void TestB() 
{ 
    Bitmap B = Test1(); 
    B.Dispose(); 
} 

यहां बी बनाया जा रहा है और निपटान बुला रहा है। इसका मतलब यह नहीं है कि यह एकत्रित किया जा सकता है। एक बार कार्यक्रम विधि छोड़ देता है, बी गुंजाइश से बाहर निकलता है जिसका अर्थ यह है कि अगली बार जीसी कहा जाता है।

When to use Dispose

2

कई अच्छी यहाँ जवाब है, लेकिन मैं यह भी पसंद इंगित करने के लिए कारण लोगों ने सोचा कि आप IDisposable की जरूरत है कि एक जीसी वास्तव में MemoryCollector या यहाँ तक कि ManagedMemoryCollector नाम दिया जाना चाहिए है। गैर-प्रबंधित मेमोरी संसाधन जैसे फ़ाइलों, डीबी कॉन्स, लेन-देन, विंडोज हैंडल आदि को इकट्ठा करने के लिए आता है जब एक जीसी विशेष स्मार्ट नहीं है।

कारण यह है कि एक प्रबंधित ऑब्जेक्ट में एक अप्रबंधित संसाधन हो सकता है जो कई गीगा रैम लेता है लेकिन जीसी में यह 8 बाइट्स या उससे भी कम दिखता है।

फ़ाइलों के साथ, डीबी कॉन्स और इतने पर आप अक्सर अप्रबंधित संसाधनों को मुक्त करने और लॉकिंग समस्याओं से बचने के लिए जितनी जल्दी हो सके उन्हें बंद करना चाहते हैं।

विंडोज हैंडल के साथ हमारे पास चिंता करने के लिए धागा संबंध है। चूंकि एक जीसी एक समर्पित धागे में चलता है कि थ्रेड हमेशा विंडोज हैंडल को मुक्त करने के लिए गलत धागा होता है।

तो जीसी प्रबंधित स्मृति को लीक करने और कोड अव्यवस्था को कम करने से बचने में बहुत मदद करता है लेकिन एक को अभी भी अप्रबंधित संसाधन ASAP जारी करना चाहिए।

() कथन का उपयोग एक आशीर्वाद है।

पीएस। प्रायः मैं आईडीस्पोजेबल को लागू करता हूं, भले ही मेरे पास कोई प्रत्यक्ष अप्रबंधित संसाधन न हो, फिर भी यह आयात सभी सदस्य चरों को सूचित करने के लिए नहीं है जो अक्षम किए गए आईडीआईस्पोजेबल को लागू करते हैं।

0

यह ध्यान देने योग्य हो सकता है कि निपटान निपटाना वास्तव में कुछ भी नहीं कर सकता है। यह ऑब्जेक्ट को डेटाबेस कनेक्शन और अप्रबंधित संसाधनों जैसे संसाधनों को साफ करने का मौका देता है। यदि आपके पास कोई ऑब्जेक्ट है जिसमें डेटाबेस कनेक्शन जैसे एक अप्रबंधित संसाधन शामिल है, तो निपटान ऑब्जेक्ट को बताएगा कि यह उन संदर्भों को साफ़ करने का समय है।

कचरा संग्रह में मौलिक सवाल यह है, "क्या यह वस्तु तक पहुंचा जा सकता है?"जब तक आपके ऑब्जेक्ट का संदर्भ है (या ऑब्जेक्ट पदानुक्रम में कहीं भी इस ऑब्जेक्ट का संदर्भ है), ऑब्जेक्ट कचरा नहीं होगा।

उदाहरण:

ओब्जा एक ओबीजेबी बनाता है, जो ओबीजेसी बनाता है। ओबीजे सी कचरा नहीं होगा जब तक कि अब ओबीजेबी द्वारा संदर्भित नहीं किया जाता है, या जब तक ओबीजेबी का अब ओब्जा द्वारा संदर्भित नहीं किया जाता है, या जब तक कोई ऑब्जेक्ट नहीं होता है ObjA।

फिर, सवाल पूछने के लिए है, "इस वस्तु वर्तमान में कुछ भी द्वारा कोड में संदर्भित किया जा सकता है?"

+0

मुझे यह भी उल्लेख करना चाहिए था कि, सिर्फ इसलिए कि किसी ऑब्जेक्ट का संदर्भ नहीं दिया गया है, इसका मतलब यह नहीं है कि इसे तुरंत एकत्र किया जाएगा। कचरा कलेक्टर इस बात पर आधारित निर्णय लेता है कि ऑब्जेक्ट कितनी देर तक जीवित है, कितनी मेमोरी खपत होती है, और प्रणाली में मेमोरी दबाव निर्धारित करने के लिए कि क्या एकत्र करना है और कब। यह आपके सिस्टम में कचरा कलेक्टर की थोड़ी अधिक समझ लेता है ताकि वास्तव में स्मृति उपयोग को अनुकूलित किया जा सके। लेकिन जीसी में शुरुआती के लिए, यह मानना ​​सुरक्षित है कि ऑब्जेक्ट अब तक पहुंचने के बाद मेमोरी कलेक्टर द्वारा स्वामित्व में है। – Jason

+0

-1 क्योंकि यह पोस्ट जीसी और निपटान के उद्देश्य को भ्रमित करता है()। यह सच है कि अप्रबंधित संसाधनों को साफ करने के लिए निपटान() है। लेकिन इसे आपके कोड द्वारा निश्चित रूप से और स्पष्ट रूप से कहा जाता है। इसे कचरा कलेक्टर द्वारा कभी नहीं बुलाया जाएगा और निपटान() को कॉल करने से कभी भी ऑब्जेक्ट कचरा नहीं होगा। – siride

संबंधित मुद्दे