2016-02-12 6 views
9

मैं समझता हूं कि अंकुशकों और उपज कीवर्ड का उपयोग एसिंक/स्टैगर्डेड ऑपरेशंस में सहायता के लिए किया जा सकता है, क्योंकि आप कोड के अगले ब्लॉक को चलाने के लिए MoveNext() पर कॉल कर सकते हैं।जीसी आईन्यूमेरेटर और उपज के साथ कैसे काम करता है?

हालांकि, मैं वास्तव में समझ नहीं पा रहा हूं कि एन्यूमेरेटर ऑब्जेक्ट क्या है। गणक के दायरे के उपयोग में स्मृति कहां जाती है? यदि आप MoveNext() एक गणक को हर तरह से नहीं करते हैं, तो क्या यह अंततः जीसीडी प्राप्त करता है?

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

मैंने इसे प्रोफाइल करने का प्रयास किया है लेकिन अभी भी मेरे सिर को उनके चारों ओर लपेट नहीं सकता है। मैं गणनाकर्ताओं के साथ होने वाली स्कोपिंग/रेफरेंसिंग को समझ नहीं पा रहा हूं। मुझे यह भी समझ में नहीं आ रहा है कि अगर आप एक समारोह से एक बनाते हैं तो अंकुशक ऑब्जेक्ट्स के रूप में बनाए जाते हैं।

निम्न उदाहरण से पता चलता मेरी भ्रम बेहतर:

// Example enumerator 
IEnumerator<bool> ExampleFunction() 
{ 
    SomeClass heavyObject = new SomeClass(); 
    while(heavyObject.Process()) 
    { 
     yield return true; 
    } 

    if(!heavyObject.Success) 
    { 
     yield return false; 
    } 

    // In this example, we'll never get here - what happens to the incomplete Enumerator 
    // When does heavyObject get GC'd? 
    heavyObject.DoSomeMoreStuff(); 
} 

// example call - Where does this enumerator come from? 
// Is something creating it with the new keyword in the background? 
IEnumerator<bool> enumerator = ExampleFunction(); 
while(enumerator.MoveNext()) 
{ 
    if(!enumerator.Current) 
    { 
     break; 
    } 
} 

// if enumerator is never used after this, does it get destroyed when the scope ends, or is it GC'd at a later date? 
+4

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

+5

हंस ने जो कहा, उसका उदाहरण: http://goo.gl/fs4eNo – xanatos

+0

ठीक है, धन्यवाद। यह वही नहीं करता जो मुझे उम्मीद थी। क्या इसका मतलब है कि पारंपरिक साधनों की तुलना में गणक काफी भारी हैं? मैं जीसी को नीचे रखने की कोशिश कर रहा हूं लेकिन ऐसा लगता है कि मैं कभी भी नया कचरा बनाने जा रहा हूं, जब भी मैं एक नया अंकुक्रम शुरू करता हूं (और मेरे पास बहुत सारे गणक हैं)। – mGuv

उत्तर

5

आपको शायद एक गणक आंतरिक पोस्ट पढ़ना चाहिए। आंतरिक से आप इन सभी सवालों का जवाब दे सकते हैं।

एक क्रैश कोर्स: प्रत्येक इटरेटर विधि निष्पादन एक नई गणनाकर्ता वस्तु देता है। स्थानीय चर फ़ील्ड बन जाते हैं।

यदि कोई भी उस गणक वस्तु का उपयोग नहीं करता है तो यह संग्रह के लिए योग्य है। साथ ही, स्थानीय संदर्भों का निर्माण करने वाले सभी संदर्भ जीसी उद्देश्यों के लिए दूर जाते हैं।

कुछ किनारे के मामले हैं जब बिल्कुल स्थानीय चर जीसी संदर्भ होने से रोकते हैं। यदि आपके गणक काफी कम रहते हैं तो इससे कोई फर्क नहीं पड़ता।

सीएलआर नहीं जानता कि एक गणक क्या है। यह सी # कंपाइलर द्वारा उत्पन्न एक वर्ग है।

इस जवाब में xanatos से लिंक पुलिंग के बाद से यह उदाहरण है और वह एक जवाब पोस्ट करने के लिए प्रतीत नहीं होता: http://goo.gl/fs4eNo

+0

ठीक है, जो बहुत कुछ बताता है। मुझे पता नहीं था कि यह एन्युमरेटर्स के समय कितना स्वैच्छिक था। मेरे पास कई विधियां हैं जो संख्याएं वापस लौटाती हैं और मेरे पास बहुत सी चीजें कॉल/उपयोग कर रही हैं। ऐसा लगता है कि यह एक जीसी समस्या हो सकती है, क्योंकि अस्तित्व में आने वाले प्रत्येक गणक को जीसीइंग की आवश्यकता होगी। मुझे कुछ प्रोफाइल होना होगा। – mGuv

2

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

जब एक इटरेटर-विधि के अंदर yield-return - नियम बिल्कुल अंतिम बयान नहीं माना जाता है, तो इसका मतलब यह है कि जब MoveNext() को वर्तमान परिणाम कहा जाता है तो उसे वापस किया जाना चाहिए। हालांकि yield return के पीछे सब कुछ MoveNext पर कॉल के बाद चलता है, इसलिए DoSomeMoreStuff पर भी आपका कॉल।

आपका heavyObject हालांकि विधि का दायरा है, इस प्रकार यह इटेटरेटर तक रहता है - जहां इटरेटर आपके while -loop के अंदर ब्लॉक है। इसका मतलब यह है कि यदि आपका इटेटरेटर किसी भी उदाहरण को वापस नहीं करता है heavyObject तुरंत निपटान किया जाएगा, अन्यथा जब पुनरावृत्ति समाप्त हो जाती है।

3

// अगर प्रगणक इस के बाद इस्तेमाल कभी नहीं किया है, यह नष्ट हो जाता है जब गुंजाइश समाप्त होता है इकट्ठा करने के लिए

सही

पात्रता कोई संदर्भ हो रही है। जीसी के स्कोपिंग के लिए गणक के साथ कुछ खास नहीं है। जब भी वे किसी अन्य प्रकार के दायरे से बाहर निकलते हैं तो गणनाकर्ताओं ने उसी तरह से निपटारा/साफ़ किया।

+0

यदि कोई गणक कभी भी किसी फ़ंक्शन के भीतर से स्थानीय रूप से संदर्भित नहीं होता है, तो क्या यह सस्ता/तत्काल जीसीड प्राप्त करता है? मैं जीसी को पूरी तरह से समझ नहीं पा रहा हूं लेकिन मुझे पता है कि इसे कहीं भी संदर्भित नहीं किया जा सकता है लेकिन समारोह के अंदर, यह पता लगाने के लिए काफी सीधे है कि इसे साफ़ किया जा सकता है? – mGuv

+0

हां यह सही है। – CharithJ

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