सी # में कचरा संग्रह के लिए सबसे अच्छा अभ्यास


118

मेरे अनुभव में ऐसा लगता है कि ज्यादातर लोग आपको बताएंगे कि कचरा संग्रहण के लिए बाध्य करना नासमझी है लेकिन कुछ मामलों में जहां आप बड़ी वस्तुओं के साथ काम कर रहे हैं जो हमेशा 0 पीढ़ी में एकत्र नहीं होते हैं, लेकिन जहां मेमोरी एक मुद्दा है, कलेक्शन के लिए बाध्य करना ठीक है? वहाँ ऐसा करने के लिए एक सबसे अच्छा अभ्यास है?

जवाबों:


112

सबसे अच्छा अभ्यास एक कचरा संग्रह को मजबूर नहीं करना है।

MSDN के अनुसार:

"कलेक्ट को कॉल करके कचरा संग्रहण के लिए मजबूर करना संभव है, लेकिन ज्यादातर समय, इससे बचा जाना चाहिए क्योंकि इससे प्रदर्शन समस्याएं पैदा हो सकती हैं।"

हालाँकि, यदि आप मज़बूती से अपने कोड का परीक्षण करके यह पुष्टि कर सकते हैं कि कॉलिंग कलेक्ट () का नकारात्मक प्रभाव नहीं पड़ेगा, तो आगे बढ़ें ...

बस यह सुनिश्चित करने की कोशिश करें कि वस्तुओं को तब साफ किया जाए जब आपको उनकी आवश्यकता नहीं है। यदि आपके पास कस्टम ऑब्जेक्ट्स हैं, तो "स्टेटमेंट का उपयोग करके" और आईडीसोफ़ायर इंटरफ़ेस का उपयोग करें।

इस लिंक में स्मृति / कचरा संग्रह आदि को मुक्त करने के संबंध में कुछ अच्छी व्यावहारिक सलाह है:

http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx


3
इसके अलावा, आप अलग-अलग लेटेंसीमोड के msdn.microsoft.com/en-us/library/bb384202.aspx
David d e Freitas

4
यदि आपकी वस्तुएँ अप्रबंधित मेमोरी की ओर इशारा करती हैं, तो आप GC संग्रहकर्ता को GC.AddMemoryPressure Api ( msdn.microsoft.com/en-us/library/… ) के माध्यम से बता सकते हैं । यह कचरा संग्रहकर्ता को संग्रह एल्गोरिदम के साथ हस्तक्षेप किए बिना आपके सिस्टम के बारे में अधिक जानकारी देता है।
18

+1: * "स्टेटमेंट का उपयोग करते हुए" और आईडीसॉफ़र इंटरफ़ेस का उपयोग करते हुए देखें। * मैं अंतिम उपाय के रूप में मजबूर करने पर भी विचार नहीं करूंगा - अच्छी सलाह ('अस्वीकरण' के रूप में पढ़ें)। हालांकि, मैं बैक-एंड ऑपरेशन में एक सक्रिय संदर्भ खोने के लिए एक यूनिट टेस्ट में संग्रह को मजबूर कर रहा हूं - आखिरकार ए TargetOfInvocationNullException
15

33

इसे इस तरह देखें - क्या रसोई के कचरे को बाहर फेंकने के लिए यह अधिक कुशल है जब कचरा 10% हो या इसे बाहर निकालने से पहले इसे भरने दें?

इसे भरने नहीं देने से, आप अपना समय और बाहर कचरा बिन से चलने के लिए बर्बाद कर रहे हैं। जब जीसी थ्रेड चलता है तो यह अनुरूप होता है - सभी प्रबंधित थ्रेड निलंबित होते हैं जब यह चल रहा होता है। और अगर मैं गलत नहीं हूं, तो जीसी धागे को कई एपडोमेंस के बीच साझा किया जा सकता है, इसलिए कचरा संग्रह उन सभी को प्रभावित करता है।

बेशक, आप एक ऐसी स्थिति का सामना कर सकते हैं, जहां आप जल्द ही कभी भी कूड़ेदान में कुछ भी नहीं जोड़ेंगे - कहें, अगर आप छुट्टी लेने जा रहे हैं। फिर, बाहर जाने से पहले कचरा फेंकना एक अच्छा विचार होगा।

यह एक बार हो सकता है कि एक जीसी को मजबूर करने में मदद मिल सकती है - यदि आपका प्रोग्राम बेकार है, तो उपयोग में आने वाली मेमोरी कचरा-एकत्र नहीं है क्योंकि कोई आवंटन नहीं है।


5
यदि आपके पास एक बच्चा था जो मर जाता था यदि आप इसे एक मिनट से अधिक समय तक छोड़ देते थे, और आपके पास केवल कभी-कभी कचरा को संभालने के लिए एक मिनट होता था, तो आप एक बार में सभी के बजाय हर बार थोड़ा सा करना चाहते हैं। दुर्भाग्य से, जीसी :: कलेक्ट () विधि किसी भी अधिक तेज नहीं है जितनी बार आप इसे कहते हैं। तो एक रीयलटाइम इंजन के लिए, यदि आप बस डिस्पोज़ तंत्र का उपयोग नहीं कर सकते हैं और GC पूल को अपना डेटा दे सकते हैं, तो आपको मेरे जवाब के अनुसार एक प्रबंधित प्रणाली का उपयोग नहीं करना चाहिए (शायद इस एक के नीचे, योग्य)।
जिन

1
मेरे मामले में, मैं एक ए * (सबसे छोटा रास्ता) एल्गोरिथ्म चला रहा हूं जो कि केवल इसे ट्यून करने के लिए है ... जो कि उत्पादन में, केवल एक बार (प्रत्येक "मैप" पर) चलाया जाएगा। इसलिए मैं चाहता हूं कि जीसी प्रत्येक पुनरावृत्ति से पहले किया जाए, मेरे "प्रदर्शन मापा ब्लॉक" के बाहर, क्योंकि मुझे लगता है कि उत्पादन में स्थिति को और करीब से देखता है, जिसमें प्रत्येक "मानचित्र" को नेविगेट करने के बाद जीसी को मजबूर किया जाना चाहिए।
corlettk

मापा ब्लॉक से पहले जीसी को कॉल करना वास्तव में उत्पादन की स्थिति को मॉडल नहीं करता है, क्योंकि उत्पादन में जीसी अप्रत्याशित समय में किया जाएगा। इसे कम करने के लिए, आपको एक लंबा माप लेना चाहिए जिसमें कई जीसी निष्पादन शामिल होंगे, और जीसी के दौरान चोटियों को आपके विश्लेषण और आंकड़ों में शामिल किया जाएगा।
राणा

32

ज्यादातर मामलों में सबसे अच्छा अभ्यास एक कचरा संग्रह के लिए मजबूर नहीं करना है। (मैंने जो भी सिस्टम पर काम किया है, उसने कचरा संग्रहण के लिए मजबूर किया था, समस्याओं को रेखांकित किया था कि अगर हल किया जाता तो कचरा संग्रह को मजबूर करने की आवश्यकता को हटा दिया जाता, और इस प्रणाली को बहुत ऊपर उठा दिया।)

ऐसे कुछ मामले हैं जब आप स्मृति उपयोग के बारे में अधिक जानते हैं तो कचरा कलेक्टर करता है। यह एक बहु उपयोगकर्ता अनुप्रयोग, या एक ऐसी सेवा में सच होने की संभावना नहीं है जो एक समय में एक से अधिक अनुरोधों का जवाब दे रही है।

हालांकि कुछ बैच प्रकार के प्रसंस्करण में आप अधिक जानते हैं तो जीसी। उदाहरण के लिए एक आवेदन पर विचार करें।

  • कमांड लाइन पर फ़ाइल नामों की एक सूची दी गई है
  • एकल फ़ाइल संसाधित करता है, फिर परिणाम फ़ाइल पर परिणाम लिखता है।
  • फ़ाइल को संसाधित करते समय, बहुत सारी इंटरलिंक्ड ऑब्जेक्ट बनाता है जिसे तब तक एकत्र नहीं किया जा सकता है जब तक कि फ़ाइल का प्रसंस्करण पूरा न हो जाए (उदाहरणार्थ एक पार्स ट्री)
  • यह संसाधित की गई फ़ाइलों के बीच बहुत अधिक स्थिति नहीं रखता है

आप एक केस बनाने में सक्षम हो सकते हैं (सावधानी से) परीक्षण के बाद कि आपको प्रत्येक फ़ाइल को संसाधित करने के बाद एक पूर्ण कचरा संग्रह को बाध्य करना चाहिए।

एक अन्य मामला एक सेवा है जो कुछ वस्तुओं को संसाधित करने के लिए हर कुछ मिनटों में उठता है, और सोते समय कोई भी स्थिति नहीं रखता है । फिर सोने के लिए जाने से पहले एक पूर्ण संग्रह को मजबूर करना सार्थक हो सकता है।

केवल एक संग्रह के लिए मजबूर करने पर विचार करने का समय है जब मुझे पता है कि हाल ही में बहुत सी वस्तु बनाई गई थी और वर्तमान में बहुत कम वस्तुओं को संदर्भित किया गया है।

मेरे पास एक कचरा संग्रह एपीआई होगा जब मैं एक जीसी को अपने आप को मजबूर करने के बिना इस प्रकार के बारे में संकेत दे सकता था।

" रिको मारियानी का प्रदर्शन टिडबिट्स " भी देखें


2
सादृश्य: Playschool (सिस्टम) crayons (संसाधन) रखता है। बच्चों की संख्या (कार्यों) और रंगों की कमी के आधार पर, शिक्षक (.Net) यह तय करता है कि बच्चों के बीच कैसे आवंटन और साझा किया जाए। जब एक दुर्लभ रंग का अनुरोध किया जाता है, तो शिक्षक पूल से आवंटित कर सकता है या एक के लिए देख सकता है जिसका उपयोग नहीं किया जा रहा है। शिक्षक के पास समय-समय पर अप्रयुक्त क्रेयॉन (कचरा एकत्र करना) को चीजों को सुव्यवस्थित रखने के लिए (संसाधन उपयोग का अनुकूलन) करने का विवेक है। आम तौर पर एक अभिभावक (प्रोग्रामर) सर्वश्रेष्ठ कक्षा क्रेयॉन टिडिंग पॉलिसी को पूर्व निर्धारित नहीं कर सकता है। एक बच्चे की अनुसूचित झपकी अन्य बच्चों के रंग में हस्तक्षेप करने के लिए एक अच्छा क्षण होने की संभावना नहीं है।
एलन डे

1
@AlanK, मुझे यह पसंद है, जब बच्चे दिन के लिए घर जाते हैं, तो शिक्षकों के लिए इसका बहुत अच्छा समय सहायक होता है कि बच्चों को रास्ते में आने के बिना एक अच्छा काम करना। (हाल ही में मैंने जिन प्रणालियों पर काम किया है, उन्होंने जीसी को बल देने के ऐसे समय में सेवा प्रक्रिया को फिर से शुरू किया है।)
इयान

21

मुझे लगता है कि रिको मरिअनी द्वारा दिया गया उदाहरण अच्छा था: यदि आवेदन की स्थिति में कोई महत्वपूर्ण परिवर्तन होता है तो जीसी को ट्रिगर करना उचित हो सकता है। उदाहरण के लिए, दस्तावेज़ संपादक में जीसी को ट्रिगर करना ठीक हो सकता है जब कोई दस्तावेज़ बंद होता है।


2
या बस एक बड़ी सन्निहित वस्तु को खोलने से पहले जिसने असफलता का इतिहास दिखाया है और अपनी ग्रैन्युलैरिटी बढ़ाने के लिए कोई कुशल प्रस्ताव प्रस्तुत नहीं करता है।
क्रुकसेक

17

प्रोग्रामिंग में कुछ सामान्य दिशानिर्देश हैं जो निरपेक्ष हैं। आधा समय, जब कोई कहता है कि 'आप इसे गलत कर रहे हैं', वे सिर्फ एक निश्चित मात्रा में हठधर्मिता कर रहे हैं। सी में, यह स्वयं-संशोधित कोड या थ्रेड्स जैसी चीजों से डरता था, जीसी भाषाओं में यह जीसी को मजबूर कर रहा है या वैकल्पिक रूप से जीसी को चलने से रोक रहा है।

जैसा कि ज्यादातर दिशा-निर्देशों और अंगूठे के अच्छे नियमों (और अच्छे डिजाइन प्रथाओं) के साथ होता है, ऐसे दुर्लभ अवसर हैं जहां यह स्थापित मानक के आसपास काम करने का कोई मतलब नहीं है। आपको इस मामले को समझने के लिए बहुत सुनिश्चित होना चाहिए, कि आपके मामले को वास्तव में सामान्य अभ्यास के निरस्तीकरण की आवश्यकता है, और यह कि आप उन जोखिमों और दुष्प्रभावों को समझते हैं जो आप पैदा कर सकते हैं। लेकिन ऐसे मामले हैं।

प्रोग्रामिंग समस्याएं व्यापक रूप से भिन्न हैं और एक लचीली दृष्टिकोण की आवश्यकता है। मैंने ऐसे मामलों को देखा है जहां यह जीसी को कचरा एकत्र की गई भाषाओं और स्थानों पर ब्लॉक करने का मतलब है, जहां यह स्वाभाविक रूप से होने की प्रतीक्षा करने के बजाय इसे ट्रिगर करने के लिए समझ में आता है। 95% समय, इन दोनों में से किसी एक का संकेत होगा कि समस्या सही से संपर्क नहीं कर रही है। लेकिन 20 में 1 बार, शायद इसके लिए एक वैध मामला है।


12

मैंने कचरा संग्रह को बाहर करने की कोशिश नहीं करना सीखा है। उस के साथ कहा, मैं सिर्फ usingफ़ाइल I / O या डेटाबेस कनेक्शन जैसे अप्रबंधित संसाधनों से निपटने के लिए कीवर्ड का उपयोग करने के लिए छड़ी ।


27
संकलक? संकलक का जीसी के साथ क्या संबंध है? :)
क्रिस्टोफर एएपी

1
कुछ भी नहीं, यह केवल कोड का संकलन और अनुकूलन करता है। और इसका निश्चित रूप से CLR ... या .NET से भी कोई लेना-देना नहीं है।
कोन

1
बहुत बड़ी छवियों की तरह बहुत सी मेमोरी पर कब्जा करने वाली वस्तुएं तब तक एकत्रित हो सकती हैं, जब तक कि आप स्पष्ट रूप से कचरा इकट्ठा नहीं करते। मुझे लगता है कि यह (बड़ी वस्तुएं) ओपी का मुद्दा था, कमोबेश।
कोड

1
एक बार उपयोग करने से यह सुनिश्चित हो जाएगा कि यह जीसी के लिए निर्धारित है, क्योंकि यह गुंजाइश के उपयोग से बाहर है। जब तक कंप्यूटर में विस्फोट नहीं होता, तब तक उस मेमोरी को सबसे अधिक साफ किया जाएगा।
कोन

9

निश्चित नहीं है कि यह एक सर्वोत्तम अभ्यास है, लेकिन जब लूप में बड़ी मात्रा में छवियों के साथ काम किया जाता है (यानी बहुत सारे ग्राफिक्स / छवि / बिटमैप ऑब्जेक्ट बनाने और निपटाने), तो मैं नियमित रूप से GC.Collect देता हूं।

मुझे लगता है कि मैं कहीं पढ़ता हूं कि जीसी केवल तभी चलता है जब प्रोग्राम (ज्यादातर) बेकार होता है, और एक गहन लूप के बीच में नहीं, ताकि वह एक ऐसे क्षेत्र की तरह दिख सके जहां मैनुअल जीसी समझ में आ सके।


क्या आप सुनिश्चित हैं कि आपको इसकी आवश्यकता है? जीसी एकत्रित करेगा यदि उसे मेमोरी की आवश्यकता है, भले ही आपका कोड निष्क्रिय न हो।
कोनराड रुडोल्फ

सुनिश्चित नहीं है कि यह .net 3.5 SP1 में अब कैसे है, लेकिन पहले (1.1 और मुझे विश्वास है कि मैंने 2.0 के खिलाफ परीक्षण किया है) यह स्मृति उपयोग में अंतर करता है। जीसी पाठ्यक्रम हमेशा कलेक्ट जब जरूरत का होगा, लेकिन आप अभी भी राम की 100 megs बर्बाद कर जब आप केवल 20. यद्यपि एक few'more परीक्षण की जरूरत की जरूरत खत्म हो सकता है
माइकल Stum

2
जब मेमोरी 0 एक निश्चित सीमा (उदाहरण 1MB) तक पहुँचती है, तो जीसी को ट्रिगर किया जाता है, न कि जब "कुछ निष्क्रिय होता है"। अन्यथा आप केवल ऑब्जेक्ट्स को आवंटित और तुरंत त्याग कर एक लूप में आउटऑफमेरी एक्ससेप्शन के साथ समाप्त हो सकते हैं।
liggett78

5
यदि कोई अन्य प्रक्रियाओं की आवश्यकता नहीं है, तो 100megs RAM व्यर्थ नहीं है। यह आपको एक अच्छा प्रदर्शन को बढ़ावा दे रहा है :-P
ओरियन एडवर्ड्स

9

एक मामला मुझे हाल ही में सामना करना पड़ा GC.Collect()था कि छोटे सी + ऑब्जेक्ट्स में लिपटे बड़े सी ++ ऑब्जेक्ट्स के साथ काम करते समय मैन्युअल कॉल की आवश्यकता थी, जो बदले में सी # से एक्सेस किए गए थे।

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


6
इसे हल करने का एक बेहतर तरीका GC.AddMemoryPressure (ApproximateSizeOfUnmanagedResource)कंस्ट्रक्टर में कॉल करके और बाद GC.RemoveMemoryPressure(addedSize)में फाइनल में है। इस तरह कचरा संग्रहकर्ता स्वचालित रूप से चलेगा, जो अप्रबंधित संरचनाओं के आकार को ध्यान में रखेगा। stackoverflow.com/questions/1149181/…
ह्यूगो जून

और समस्या को हल करने का एक बेहतर तरीका वास्तव में डिस्पोज़ () को कॉल करना है, जिसे आप वैसे भी करने वाले हैं।
फबस्प्रो

2
सबसे अच्छा तरीका है कि प्रयोग संरचना का उपयोग करें। कोशिश करो / अंत में .Dispose एक परेशानी है
TamusJRoyce

7

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

  1. क्या आपके पास अपने कोड में कुछ ऐसा है जो आवश्यकता से अधिक बड़े स्तर पर वस्तुओं की घोषणा कर रहा है
  2. क्या मेमोरी का उपयोग वास्तव में बहुत अधिक है
  3. GC.Collect () का उपयोग करने से पहले और बाद में प्रदर्शन की तुलना करके देखें कि क्या यह वास्तव में मदद करता है।

5

मान लीजिए कि आपके प्रोग्राम में मेमोरी लीकेज नहीं है, ऑब्जेक्ट्स जमा होते हैं और Gen 0 में GC-ed नहीं हो सकता क्योंकि: 1) वे लंबे समय से संदर्भित हैं इसलिए Gen1 & Gen2 में जाएं; 2) वे बड़े ऑब्जेक्ट हैं (> 80K) तो LOH (बड़े ऑब्जेक्ट हीप) में आते हैं। और LOH Gen0, Gen1 & Gen2 की तरह कॉम्पैक्टिंग नहीं करता है।

".NET मेमोरी" के प्रदर्शन काउंटर की जांच करें आप देख सकते हैं कि 1) समस्या वास्तव में समस्या नहीं है। आम तौर पर, हर 10 Gen0 GC 1 Gen1 GC को ट्रिगर करेगा, और हर 10 Gen1 GC 1 Gen2 GC को ट्रिगर करेगा। सैद्धांतिक रूप से, GC1 & GC2 GC-ed कभी नहीं हो सकता है यदि GC0 पर कोई दबाव नहीं है (यदि प्रोग्राम मेमोरी उपयोग वास्तव में वायर्ड है)। मेरे साथ ऐसा कभी नहीं होता।

समस्या 2 के लिए), आप सत्यापित कर सकते हैं कि LOH फूला हुआ है या नहीं, यह सत्यापित करने के लिए ".NET मेमोरी" प्रदर्शन काउंटर। यदि यह वास्तव में आपकी समस्या का मुद्दा है, तो शायद आप एक बड़े ऑब्जेक्ट-पूल बना सकते हैं क्योंकि यह ब्लॉग http://blogs.msdn.com/yunjin/archive/2004/01/27/63642.aspx बताता है ।


4

LOH पर बड़ी वस्तुओं का आवंटन किया जाता है (बड़े ऑब्जेक्ट हीप), जीन 0. पर नहीं। यदि आप कह रहे हैं कि उन्हें ग्रेन-कलेक्ट नहीं किया जाता है, तो आप सही हैं। मेरा मानना ​​है कि वे केवल तभी एकत्रित होते हैं जब पूर्ण जीसी चक्र (पीढ़ियों 0, 1 और 2) होता है।

कहा जा रहा है, मेरा मानना ​​है कि जब आप बड़ी वस्तुओं के साथ काम करते हैं और मेमोरी दबाव बढ़ता जा रहा है, तो दूसरी तरफ जीसी मेमोरी को अधिक आक्रामक रूप से समायोजित और एकत्रित करेगा।

यह कहना कठिन है कि क्या और किन परिस्थितियों में इकट्ठा किया जाए या नहीं। मैं GC.Collect () डायलॉग विंडो / फॉर्म्स को कई कंट्रोल आदि से निपटाने के बाद करता था (क्योंकि समय के साथ फॉर्म और उसके कंट्रोल जनरल 2 में खत्म हो जाते हैं क्योंकि बिजनेस ऑब्जेक्ट्स के कई इंस्टेंसेस बनाने / बहुत डेटा लोड करने में - नहीं स्पष्ट रूप से बड़ी वस्तुएं), लेकिन वास्तव में ऐसा करने से दीर्घकालिक में कोई सकारात्मक या नकारात्मक प्रभाव नहीं देखा गया।


4

मैं यह जोड़ना चाहूंगा कि: GC.Collect () (+ WaitForPendingFinalizers ()) को कॉल करना कहानी का एक हिस्सा है। जैसा कि दूसरों द्वारा सही उल्लेख किया गया है, GC.COllect () गैर-नियतात्मक संग्रह है और इसे GC (स्वयं CLR) के विवेक पर छोड़ दिया गया है। यहां तक ​​कि अगर आप WaitForPendingFinalizers के लिए एक कॉल जोड़ते हैं, तो यह निर्धारक नहीं हो सकता है। इस msdn लिंक से कोड लें और 1 या 2 के रूप में ऑब्जेक्ट लूप पुनरावृत्ति के साथ कोड को चलाएं। आपको पता चलेगा कि गैर-नियतात्मक अर्थ क्या है (ऑब्जेक्ट के विनाशकर्ता में एक विराम बिंदु सेट करें)। संक्षेप में, विध्वंसक को तब नहीं बुलाया जाता है जब वेट (..) द्वारा केवल 1 (या 2) सुस्त वस्तुएं होती हैं।

यदि आपका कोड अप्रबंधित संसाधनों (उदा: बाहरी फ़ाइल हैंडल) के साथ काम कर रहा है, तो आपको विध्वंसक (या अंतिम रूप) लागू करना होगा।

यहाँ एक दिलचस्प उदाहरण है:

नोट : यदि आपने MSDN से उपरोक्त उदाहरण को पहले ही आज़मा लिया है, तो निम्न कोड हवा को साफ़ करने वाला है।

class Program
{    
    static void Main(string[] args)
        {
            SomePublisher publisher = new SomePublisher();

            for (int i = 0; i < 10; i++)
            {
                SomeSubscriber subscriber = new SomeSubscriber(publisher);
                subscriber = null;
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();

            Console.WriteLine(SomeSubscriber.Count.ToString());


            Console.ReadLine();
        }
    }

    public class SomePublisher
    {
        public event EventHandler SomeEvent;
    }

    public class SomeSubscriber
    {
        public static int Count;

        public SomeSubscriber(SomePublisher publisher)
        {
            publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
        }

        ~SomeSubscriber()
        {
            SomeSubscriber.Count++;
        }

        private void publisher_SomeEvent(object sender, EventArgs e)
        {
            // TODO: something
            string stub = "";
        }
    }

मेरा सुझाव है, पहले विश्लेषण करें कि आउटपुट क्या हो सकता है और फिर चला जाए और फिर नीचे दिए गए कारण को पढ़ें:

{कार्यक्रम समाप्त होने के बाद विध्वंसक केवल अनुमानित रूप से कहा जाता है। } वस्तु को निर्धारक रूप से साफ करने के लिए, व्यक्ति को आईडीसोपॉलिफ़िक लागू करना चाहिए और डिस्पोज़ () को स्पष्ट कॉल करना चाहिए। यही सार है! :)


2

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

.NET GC अच्छी तरह से डिज़ाइन किया गया है और अनुकूली होने के लिए तैयार है, जिसका अर्थ है कि यह GC0 / 1/2 सीमा को आपके प्रोग्राम मेमोरी उपयोग की "आदत" के अनुसार समायोजित कर सकता है। इसलिए, कुछ समय चलने के बाद यह आपके प्रोग्राम के अनुकूल हो जाएगा। एक बार जब आप GC.Collect को स्पष्ट रूप से लागू करते हैं, तो थ्रेसहोल्ड रीसेट हो जाएगा! और .NET को आपके प्रोग्राम की "आदत" के अनुकूल होने के लिए फिर से समय देना होगा।

मेरा सुझाव हमेशा .NET GC पर भरोसा है। कोई भी मेमोरी प्रॉब्लम सरफेस, ".NET मेमोरी" परफॉर्मेंस काउंटर की जाँच करें और अपने कोड का निदान करें।


6
मुझे लगता है कि यह बेहतर है कि आप इस उत्तर को अपने पिछले उत्तर के साथ मिला दें।
सलामन्डर २०० Sal

1

यकीन नहीं होता है कि यह सबसे अच्छा अभ्यास है ...

सुझाव: अनिश्चित होने पर इसे या कुछ भी लागू न करें। तथ्यों का पता चलने पर पुनर्मूल्यांकन करें, उसके बाद प्रदर्शन परीक्षण से पहले / बाद में सत्यापित करें।


0

हालाँकि, यदि आप मज़बूती से अपने कोड का परीक्षण करके यह पुष्टि कर सकते हैं कि कॉलिंग कलेक्ट () का नकारात्मक प्रभाव नहीं पड़ेगा, तो आगे बढ़ें ...

IMHO, यह कहने के समान है "यदि आप यह साबित कर सकते हैं कि आपके कार्यक्रम में भविष्य में कभी कोई कीड़े नहीं होंगे, तो आगे बढ़ें ..."

सभी गंभीरता में, जीसी को मजबूर करना डिबगिंग / परीक्षण उद्देश्यों के लिए उपयोगी है। यदि आपको ऐसा लगता है कि आपको इसे किसी अन्य समय पर करने की आवश्यकता है, तो या तो आपसे गलती हो जाती है, या आपका कार्यक्रम गलत बनाया गया है। किसी भी तरह, समाधान जीसी मजबूर नहीं है ...


"तो या तो आप गलत हैं, या आपका कार्यक्रम गलत बनाया गया है। किसी भी तरह, समाधान जीसी को मजबूर नहीं कर रहा है ..." निरपेक्षता लगभग हमेशा सच नहीं होती है। कुछ असाधारण परिस्थितियां हैं जो इसे समझ में आती हैं।
रोल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.