2010-01-05 16 views
6

Publiqué una pregunta no hace mucho sobre cómo mi programa esencialmente tenía una pérdida de memoria: vea here. Ahora lo he rastreado específicamente a algún código en el que copie los bytes sin formato de un objeto Bitmap en una matriz administrada. El código en cuestión:Uso seguro de Marshal.Copia de datos brutos de mapas de bits a la matriz administrada

public class FastBitmap 
{ 
    ... 
    private byte[] rgbValues; 
    private int height; 
    private int width; 
    private Bitmap image; 

    public FastBitmap(Bitmap plainBitmap) 
    { 
     width = plainBitmap.Width; 
     height = plainBitmap.Height; 
     image = new Bitmap(plainBitmap); 
     LockPixels(new Rectangle(0, 0, image.Width, image.Height)); 
    } 

    private void LockPixels(Rectangle area) 
    { 
     if (locked) 
      return; 
     locked = true; 
     BitmapData bitmapData = image.LockBits(area, ImageLockMode.ReadWrite, 
           PixelFormat.Format24bppRgb); 
     IntPtr ptr = bitmapData.Scan0; 
     int stride = bitmapData.Stride; 
     int numBytes = image.Width * image.Height * 3; 
     rgbValues = new byte[numBytes]; 
     for (int r = 0; r < image.Height; ++r) 
     Marshal.Copy(new IntPtr((int)ptr + stride * r), 
          rgbValues, image.Width * 3 * r, image.Width * 3); 
    } 
} 

Así que eso es todo el alcance del código que está causando la memoria no se está recuperando, y me imagino que tiene algo que ver con la Marshal.Copy() aunque había asumido que desde que estaba copiando de un mapa de bits (¿se había limpiado solo?) a una matriz administrada, no había ningún problema.

Entonces la pregunta: ¿Es necesario limpiar el objeto Bitmap, ya sea a través de una interfaz IDisposable, o algo similar. ¿Qué (si hay algo) es intrínsecamente incorrecto con el uso de Marshal.Copy() en esta situación, y dónde puedo solucionar el problema?

Gracias

Para que sepan que he probado el siguiente código, para verificar que efectivamente es esta la causa del problema:

Bitmap bmp = new Bitmap(1000, 1000); 
for (int n = 0; n < 100; ++n) 
{ 
    FastBitmap fb = new FastBitmap(bmp); 
} 

Al principio y al final de esta secuencia de la memoria global el uso se ha incrementado en algo así como 320 MB y no desaparece, independientemente de cuánto tiempo espere.

Respuesta

8

Ha olvidado llamar a image.UnlockBits (bitmapData);

+1

Muchas gracias, horas de frustración y es tan simple como eso. – DeusAduro

+0

Parece que se pierde el segundo fragmento de código, la función 'UnlockBitmap' (que llama a 'UnlockBits'), de este artículo: http://www.devx.com/webdev/Article/44658/1763/page/2 – rwong

Cuestiones relacionadas