2012-06-13 8 views
5

की करीबी विधि मैंने कुछ कोड लिखा है जो XmlDocument ऑब्जेक्ट का उपयोग करके XML दस्तावेज़ लोड करता है ताकि उसके नोड्स को गिनने के लिए। यहां विधि है:सी #: Xml.Load (फ़ाइल)

XmlDocument xml = new XmlDocument(); 
xml.Load(textBox1.Text); 
XmlNodeList nodes = xml.SelectNodes("//File"); 
foreach (XmlNode node in nodes) 
{ 
    number_of_childs++; 
} 

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

उत्तर

12

सं। XmlDocument कक्षा IDisposable लागू नहीं करती है, इसलिए इच्छा पर संसाधनों को जारी करने के लिए इसे मजबूर करने का कोई तरीका नहीं है। क्या तुम सच में तुरंत XmlDocument द्वारा प्रयुक्त स्मृति को मुक्त करने की जरूरत है, एक ही रास्ता करने के लिए है कि निम्न कार्य करना होगा:

nodes = null; 
xml = null; 
GC.Collect(); 

कचरा कलेक्टर एक अलग थ्रेड पर काम करता है, तो यह अभी भी तत्काल नहीं हो सकता है। अपने कोड के निष्पादन जारी रखने से पहले तुल्यकालिक होने के लिये कचरा संग्रहण के लिए मजबूर करने के लिए, आप भी, WaitForPendingFinalizers कॉल करना होगा जैसे:

nodes = null; 
xml = null; 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

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

+0

उस जानकारी के लिए धन्यवाद, लेकिन यह काम नहीं किया है, मैंने आपके कोड का टुकड़ा लागू किया है लेकिन यह अभी भी स्मृति की एक ही राशि को आरक्षित करता है। –

+0

@ आर। वेक्टर मेरा संपादन देखें। –

+0

हाँ यह काम करता है, लेकिन ऐप का दूसरा चरण प्रत्येक नोड को पढ़ना और इसे एक सूचीदृश्य में टाइप करना है, इसलिए समस्या अभी भी मौजूद है, लेकिन अगर मैं xml के प्रत्येक नोड को पढ़ सकता हूं और जब यह था कहीं सफलतापूर्वक संग्रहीत <<< स्मृति प्रबंधन के लिए उस तरह से बेहतर होगा। –

2

यदि आपको XML में हेरफेर करने की आवश्यकता नहीं है, तो XMLReader का उपयोग कर एक्सएमएल पढ़ें, जो कम स्मृति तीव्र ऑपरेशन के साथ चल रहा है और सबसे तेज़ है।

1

अपनी ऑब्जेक्ट को शून्य पर सेट करने की कोई आवश्यकता नहीं है। जीसी यह इंगित करने में सक्षम होना चाहिए कि दस्तावेज़ का उपयोग किसी और पर नहीं किया जा रहा है या नहीं। यह स्वचालित रूप से हो जाएगा क्योंकि स्मृति की आवश्यकता है, लेकिन यदि आप इसे साफ़ करना चाहते हैं तो तुरंत GC.Collect() पर कॉल करें। आगे की चर्चा के लिए this thread देखें।

+1

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

+0

@ स्टेवन डॉगगार्ट, आपका कथन केवल डीबग बिल्ड में ही सच है। रिलीज बिल्ड में, शून्य पर सेट करना आवश्यक नहीं है - जीसी यह देखने के लिए पर्याप्त स्मार्ट है कि इसे बिना शून्य के सेट किए संदर्भित किया गया है। उदाहरण के लिए http://stackoverflow.com/questions/5545288/garbage-collection-of-orphaned-objects-tree-nodes-works-for-the-release-exe देखें। –

+0

@ मैटस्मिथ यह आश्चर्यजनक और दिलचस्प है। क्या ऐसा इसलिए है क्योंकि डिफॉल्ट रूप से रिलीज बिल्ड में अतिरिक्त ऑप्टिमाइज़ेशन शामिल होते हैं जो वैरिएबल को स्वचालित रूप से 'null' पर सेट करते हैं जैसे ही इसका उपयोग नहीं किया जाता है, या कुछ? –

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