2009-08-12 14 views
6

मेरे पास एक विंडोज़फॉर्म ऐप है जो स्मृति को रिसाव करने के लिए प्रतीत होता है, इसलिए मैंने उन वस्तुओं को देखने के लिए रेडगेट के एएनटीएस मेमोरी प्रोफाइलर का उपयोग किया और मुझे लगता है कि वे केवल फ़ाइनलाइज़र कतार पर ऑब्जेक्ट्स द्वारा ही आयोजित किए जाते हैं। बढ़िया, बिल्कुल फाइनेंजर कतार क्या है? क्या आप मुझे सबसे अच्छी परिभाषा के लिए इंगित कर सकते हैं? क्या आप किसी भी अनावश्यक सलाह साझा कर सकते हैं?फ़ाइनेंजर कतार और नियंत्रण + थ्रेड MethodEntry क्या हैं?

इसके अलावा, सभी finalizer कतार पर रूट जीसी वस्तुओं System.Windows.Forms.Control + ThreadMethodEntry वस्तुओं "फोन करने वाले" नाम के उदाहरण हैं। मैं देखता हूं कि यह मल्टी-थ्रेड यूआई इंटरैक्शन में शामिल है, लेकिन मुझे उससे परे बहुत कुछ पता नहीं है। मेरी स्पष्ट आलस्य को क्षमा करें और अज्ञानता स्वीकार की, लेकिन इन संसाधनों को सभी को विक्रेता के घटक के भीतर दफनाया जाता है। मैं इन मुद्दों के बारे में विक्रेता से बात कर रहा हूं, लेकिन मुझे वार्तालाप पर तेजी लाने के लिए मुझे कुछ दिशा चाहिए। क्या आप मुझे ThreadMethodEntry की सबसे उपयोगी परिभाषा पर भी इंगित कर सकते हैं? कोई अजीब सलाह?

साथ ही, क्या मुझे अंतिम वस्तु कतार पर इन वस्तुओं के बारे में भी चिंतित होना चाहिए?

अद्यतन: यह Red Gate article सहायक था।

उत्तर

14

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

अतीत में मेमोरी लीक के साथ काम करने के बाद, फाइनलज़र कतार में आपके विक्रेता की ऑब्जेक्ट्स को एक गुच्छा देखकर मैला कोड हो सकता है, लेकिन यह स्मृति रिसाव का संकेत नहीं देता है। आम तौर पर, अच्छा कोड एक निपटान विधि का पर्दाफाश करेगा जो प्रबंधित और अप्रबंधित दोनों संसाधनों को एकत्र करेगा, और ऐसा करने में, GC.SuppressFinalize() के माध्यम से स्वयं को अंतिम कतार से हटा दें। इसलिए, यदि विक्रेता की वस्तुएं एक निपटान विधि को कार्यान्वित करती हैं, और आपका कोड इसे कॉल नहीं करता है, तो यह अंतिमकर्ता कतार में ऑब्जेक्ट्स का एक गुच्छा पैदा कर सकता है।

क्या आपने समय में दो बिंदुओं के बीच एएनटीएस में स्नैपशॉट बनाने और उनके बीच बनाई गई वस्तुओं की तुलना करने की कोशिश की है? यह आपको किसी भी प्रबंधित वस्तुओं को लीक होने की पहचान करने में मदद कर सकता है।

 
System.GC.Collect(); 
System.GC.WaitForPendingFinalizers(); // this method may block while it runs the finalizers 
System.GC.Collect(); 

मैं इस कोड सामान्य रूप से चल अनुशंसा नहीं करते हैं:

इसके अलावा, अगर आप यदि स्मृति चली जाती है जब finalizers चलाए जा रहे हैं देखना चाहते हैं, यह सिर्फ के साथ परीक्षण करने के लिए प्रयास करें। यदि आप अभी काम का एक टन कर चुके हैं और बहुत सारे कचरे का निर्माण किया है तो आप इसे चलाने के लिए चाहते हैं। उदाहरण के लिए, हमारे ऐप में, हमारे कार्यों में से एक लगभग 350 एमबी कचरा बना सकता है जो एमडीआई विंडो बंद करने के बाद बर्बाद हो जाता है। चूंकि यह बहुत सारे कचरे को छोड़ने के लिए जाना जाता है, इसलिए हम कचरा संग्रह को मैन्युअल रूप से मजबूर करते हैं।

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

+0

महान जवाब के लिए धन्यवाद, पॉल। संसाधनों को साफ करने के बाद, ऑब्जेक्ट संदर्भ ग्राफ मैं दूसरे स्नैपशॉट में नई ऑब्जेक्ट्स को देखकर बात कर रहा हूं। IDISposable को लागू करने वाले ग्राफ़ में मौजूद सभी ऑब्जेक्ट्स में एक टूल टिप है जो कहती है "इस ऑब्जेक्ट के लिए डिस्प्ले() को कॉल किया गया है" लेकिन चयनित ऑब्जेक्ट में ऐसी कोई टूलटिप नहीं है। – flipdoubt

+2

ThreadMethodEntry के बारे में नोट: मुझे लगता है कि वे यूआई थ्रेड में किसी भी आमंत्रण में उपयोग किए जाते हैं। प्रत्येक कंट्रोल ऑब्जेक्ट में ThreadMethodEntry प्रकार के थ्रेड कॉलबैक की एक पंक्ति है। एक कॉलबैक थ्रेड MethodEntry को हटा देता है और इसे चलाता है। प्रत्येक थ्रेड MethodEntry ऑब्जेक्ट में आंतरिक फ़ील्ड का एक गुच्छा है। इन क्षेत्रों की जांच करने से आप यह पता लगाने में मदद कर सकते हैं कि इनमें से कौन सा विक्रेता ऑब्जेक्ट्स आ रहा है। मुझे याद नहीं है कि क्या आप एएनटीएस से यह जानकारी प्राप्त कर सकते हैं, लेकिन मुझे पता है कि आप WinDbg.dll और sos.dll (प्रबंधित डीबगर एक्सटेंशन) के माध्यम से कर सकते हैं। "विधि" प्रतिनिधि और "कॉलर" नियंत्रण देखें। –

+0

इसके अलावा, ध्यान दें कि ThreadMethodEntry ऑब्जेक्ट्स फ़ाइनलज़र को कार्यान्वित करते हैं, लेकिन उनके पास डिस्पोजेक्ट विधि नहीं है। जब वे पूरा हो जाएंगे, तो वे फाइनलजर कतार में भी चले जाएंगे। –

1

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

ThreadMethodEntry क्लास IAsyncResult का एक कार्यान्वयन है और इस वर्ग के उदाहरण आमतौर पर एसिंक्रोनस ऑपरेशंस का आह्वान करते समय बनाए जाते हैं, जैसे यूआई को अपडेट करने या Begin */End * विधियों का उपयोग करने के लिए Invoke का उपयोग करना।

0

Here's एक अच्छा ब्लॉग पोस्ट जो एक समान मुद्दे का वर्णन करता है। अधिक तकनीकी स्तर पर, आप SOS.dll (जिसे ब्लॉग पोस्ट का वर्णन करता है) और Sosex.dll का उपयोग करने के लिए देख सकते हैं ताकि आप यह काम करने में सहायता कर सकें कि इन थ्रेड MethodEntry ऑब्जेक्ट्स मेमोरी में क्यों लटक रहे हैं। इन WinDbg एक्सटेंशन में कमांड हैं जो ट्रैक कर सकते हैं कि अन्य ऑब्जेक्ट्स स्मृति में किसी विशेष ऑब्जेक्ट का संदर्भ दे रहे हैं।