2010-09-29 14 views
5

जारी नहीं करता है हमारे आवेदन में, हम System.IO.Packaging.Package वर्ग का उपयोग कर एक एक्सपीएस फ़ाइल पढ़ रहे हैं। जब हम किसी पैकेजपार्ट की स्ट्रीम से पढ़ते हैं, तो हम कार्य प्रबंधक से देख सकते हैं कि एप्लिकेशन की मेमोरी खपत बढ़ जाती है। हालांकि, जब पढ़ा जाता है, तो स्मृति खपत धारा से पढ़ने से पहले जो कुछ भी था उससे वापस नहीं आती है।पठन स्मृति

समस्या समझने के लिए, मैं एक साधारण कोड का नमूना है कि आप आवेदन WPF अकेले एक स्टैंड में उपयोग कर सकते हैं लिखा था।

public partial class Window1 : Window 
{ 
     public Window1() 
     { 
      InitializeComponent(); 

      _package = Package.Open(@"c:\test\1000pages.xps", FileMode.Open, FileAccess.ReadWrite, FileShare.None); 

     } 

     private void ReadPackage() 
     { 
      foreach (PackagePart part in _package.GetParts()) 
      { 
       using (Stream partStream = part.GetStream()) 
       { 
        byte[] arr = new byte[partStream.Length]; 
        partStream.Read(arr, 0, (int)partStream.Length); 
        partStream.Close(); 
       } 
      } 
     } 

     Package _package; 
     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      ReadPackage();  
     } 
} 

ReadPackage() विधि सभी पैकेजपार्ट ऑब्जेक्ट्स स्ट्रीम सामग्री को स्थानीय सरणी में पढ़ेगी। नमूना में, मैंने एप्लिकेशन के मेमोरी खपत परिवर्तन को आसानी से देखने के लिए पैकेज स्रोत के रूप में 1000 पेज एक्सपीएस दस्तावेज़ का उपयोग किया था। मेरी मशीन पर, स्टैंड स्टैंड अकेले ऐप की मेमोरी खपत 18 एमबी से शुरू होती है और विधि को कॉल करने के बाद 100 एमबी तक बढ़ जाती है। विधि को फिर से कॉल करने से स्मृति की खपत फिर से बढ़ सकती है लेकिन यह 100 एमबी तक गिर सकती है। हालांकि, यह अब 18 एमबी तक नहीं गिरता है।

क्या किसी ने पैकेजपर्ट का उपयोग करते समय इसका अनुभव किया है? या मैं इसे गलत इस्तेमाल कर रहा हूँ? मुझे लगता है कि पैकेजपार्ट का आंतरिक कार्यान्वयन पढ़ने वाले डेटा को कैश कर रहा है।

धन्यवाद!

+0

मुझे नहीं पता कि यह सवाल क्यों कम किया गया था। –

उत्तर

0

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

तुम सच में कैसे अपने आवेदन आप Microsoft CLR profiler उपयोग कर सकते हैं स्मृति का उपयोग करता है के विवरण को समझने चाहते हैं।

आपको क्या दिखाई नेट ढेर एक बहुत बड़ी फ़ाइल को समायोजित करने के विस्तार का एक परिणाम हो सकता है। बड़ी वस्तुएं बड़े ऑब्जेक्ट हीप (LOH) पर रखी जाती हैं और यहां तक ​​कि यदि .NET मेमोरी कचरा इकट्ठा किया जाता है तो भी मुफ्त मेमोरी ऑपरेटिंग सिस्टम पर वापस नहीं आती है। इसके अलावा, LOH पर ऑब्जेक्ट कचरा संग्रह के दौरान कभी भी नहीं चले जाते हैं और यह उपलब्ध एड्रेस स्पेस को समाप्त करने के लिए LOH को विभाजित कर सकता है, भले ही बहुत सारी मुफ्त मेमोरी हो।

किसी को भी इस जबकि PackagePart का उपयोग कर अनुभव है? या मैं इसे गलत इस्तेमाल कर रहा हूँ?

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

using (var package = Package.Open(@"c:\test\1000pages.xps", FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { 
    // ... process the package 
} 

using बयान संसाधन पैकेज द्वारा खपत के अंत में या तो पहले से ही जारी कर रहे हैं या कचरा एकत्र हो सकता है।

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

+0

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

+0

हम्म। मैंने ReadPackage() को कॉल करने के बाद GC.Collect() को कॉल करने का प्रयास किया लेकिन कुछ भी नहीं हुआ। हालांकि, मैंने _package.Close() फिर GC.Collect() को ReadPackage() के बाद बुलाया और मेमोरी उपयोग 100 एमबी से लगभग 20 एमबी तक गिर गया। तो शायद पैकेज धाराओं के संदर्भ धारण कर रहा था? – bjutus

+0

ने आपके उत्तर में आपके अपडेट देखे हैं। धन्यवाद। मैंने केवल जीसी.कोलेक्ट() को यह जांचने की कोशिश की कि स्मृति वास्तव में किसी के द्वारा सहायता नहीं कर रही है या नहीं। ऐसा लगता है कि पैकेज बंद होने तक यह है। हाँ हम पैकेज पर करीब कॉल करते हैं जब हमें इसकी आवश्यकता नहीं होती है। समस्या यह है कि यह हमारे ऐप में डेटा का मुख्य स्रोत है, इसलिए इसे ऐप के पूरे जीवनकाल में खुला रहना होगा। पैकेजपार्ट स्ट्रीम हालांकि ऐसा कुछ है जिसे हमें पूरे समय की आवश्यकता नहीं है। यही कारण है कि हम स्मृति को मुक्त करने की उम्मीद करते हैं क्योंकि हम ReadPackage() विधि का दायरा छोड़ देते हैं। हो सकता है कि पैकेज में किसी प्रकार का आंतरिक कैशिंग हो ... – bjutus

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