2011-04-30 8 views
7

मैं सोच रहा हूं कि बिटमैप्स के लिए आवंटित स्मृति का आवंटन और निपटान .NET में कैसे काम करता है।.NET और बिटमैप स्वचालित रूप से जीसी द्वारा निपटाया नहीं जाता है जब कोई स्मृति नहीं होती है

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

यदि मैं कचरा कलेक्टर को काम करता हूं, जबकि यह काम करता है।

निम्नलिखित कोड आप त्रुटि repoduce करने में सक्षम हैं के साथ:

class BitmapObject { 
    public bool Visible { 
     get { return enb; } 
     set { enb = value; } 
    } 
    private bool enb; 
    private Bitmap bmp; 
public BitmapObject(int i, bool en) 
{ 
    enb = en; 
    bmp = new Bitmap(i, i); 


    } 
} 

class Pool<T> where T : BitmapObject 
{ 
    List<T> preallocatedBitmaps = new List<T>(); 
public void Fill() { 
    Random r = new Random(); 
    for (int i = 0; i < 500; i++) { 
     BitmapObject item = new BitmapObject(500, r.NextDouble() > 0.5); 
     preallocatedBitmaps.Add(item as T); 
    } 
} 

public IEnumerable<T> Objects 
{ 
    get 
    { 
     foreach (T component in this.preallocatedBitmaps) 
     { 
      if (component.Visible) 
      { 
       yield return (T)component; 
      } 
     } 


    } 
    } 
} 

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
{ 
    for (int i = 0; i < 10; i++) 
    { 
     Test(); 

      // without this it breaks 
      //GC.Collect(); 
      //GC.WaitForPendingFinalizers(); 
     } 

     Console.ReadKey(); 
    } 

    private static void Test() { 
     Pool<BitmapObject> pool = new Pool<BitmapObject>(); 
     pool.Fill(); 

     for (int i = 0; i < 100; i++) 
     { 
      var visBitmaps = pool.Objects; 
      // do something 
     }  
    } 
} 
+2

जीसी * कभी भी मूल संसाधनों को साफ नहीं करता है, केवल बिटमैप ऑब्जेक्ट ही। आप 'निपटान() 'को कॉल करने के लिए ज़िम्मेदार हैं। –

+0

@Ed, तकनीकी रूप से सत्य होने पर, जब जीसी बिटमैप को साफ करता है तो बिटमैप का अंतिमकर्ता संसाधन का निपटान करेगा। लेकिन आप सही हैं कि आपको उस पर भरोसा नहीं करना चाहिए। – Talljoe

+0

@ टल्जोज़: हाँ, आप सही हैं, यह होगा। –

उत्तर

14

नेट Bitmap वर्ग "एक GDI + बिटमैप समाहित", इसका मतलब है कि आप एक Bitmap पर Dispose बुलाना चाहिए जब आप इसे के साथ समाप्त कर ,

"Always call Dispose before you release your last reference to the Image. Otherwise, the resources it is using will not be freed until the garbage collector calls the Image object's Finalize method."

+0

इसका मतलब है कि यदि सामान्य वर्गों में कुछ बिटमैप का उपयोग किया जाता है तो सामान्य वर्गों को IDIsposable लागू करना चाहिए और टी कक्षा द्वारा बुलाए जाने योग्य डिस्पोजेबल होना चाहिए? –

1

आप using कीवर्ड का उपयोग क्यों नहीं करते हैं। बस इसमें अपनी बिटमैप ऑब्जेक्ट को समाहित करें और कंपाइलर यह सुनिश्चित करेगा कि निपटान विधि कहा जाता है।

इसके लिए

try 
{ 
... 
} 
finally 
{ 
    ...Dispose(); 
} 
+1

क्योंकि बिटमैप एक वर्ग का एक निजी क्षेत्र हो सकता है जिसका प्रयोग सामान्य बाहरी सूची में किया जाता है ... लेकिन मुझे लगता है कि IDISposable यहां जाने का तरीका है ... –

17

बिटमैप वर्ग बस एक वाक्यात्मक शॉर्टकट अनिवार्य रूप से एक है जहाँ आप है अनदेखी कि IDisposable मौजूद है को रोकने के लिए है। यह एक जीडीआई + ऑब्जेक्ट के चारों ओर एक छोटा रैपर वर्ग है। जीडीआई + अप्रबंधित कोड है। बिटमैप अप्रबंधित स्मृति पर कब्जा करता है। बिटमैप बड़ा होने पर बहुत कुछ।

.NET कचरा कलेक्टर यह सुनिश्चित करता है कि अप्रबंधित सिस्टम संसाधन फाइनलज़र थ्रेड के साथ जारी किए जाएं। समस्या यह है कि जब आप एक कचरा संग्रह ट्रिगर करने के लिए प्रबंधित ऑब्जेक्ट्स की पर्याप्त मात्रा बनाते हैं तो यह केवल क्रिया में आता है। यह बिटमैप क्लास के लिए अच्छी तरह से काम नहीं करेगा, आप ढेर एकत्रित कचरे के पीढ़ी # 0 से पहले उनमें से हजारों को बना सकते हैं। इससे पहले कि आप वहां पहुंच सकें, आप अप्रबंधित स्मृति से बाहर चले जाएंगे।

आपके द्वारा उपयोग किए जाने वाले बिटमैप्स के जीवनकाल को प्रबंधित करने की आवश्यकता है। निपटान() विधि को कॉल करें जब आपके पास इसका उपयोग नहीं होगा। यह हमेशा सुनहरा समाधान नहीं होता है, यदि आपके पास बस बहुत से लाइव बिटमैप्स हैं तो आपको अपना दृष्टिकोण फिर से सोचना होगा। एक 64-बिट ऑपरेटिंग सिस्टम अगला समाधान है।

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

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