Bitmap.Save, gran pérdida de memoria

Tengo una aplicación donde tomo un bitmap y lo comprimo usando un GZipStream y lo envío a través de un socket, todo en la memoria. He rastreado la pérdida de memoria sucia scumbag a la siguiente línea:

frame.Save(inStream, jpegCodec, parameters); 

Navegando alrededor de la superautopista de la buena información, he encontrado numerosos temas sobre la pérdida de memoria de la clase Image en el método de guardar en varios códecs. El problema es que realmente no hay ninguna solución que pueda encontrar. Así que mis preguntas son las siguientes:

  1. Que causa esto
  2. Cómo puedo arreglar esto

Aquí está mi método completo de Write () en mi clase FrameStream donde se localiza la fuga.

 ///  /// Writes a frame to the stream ///  /// The frame to write public void Write(Bitmap frame) { using (EncoderParameter qualityParameter = new EncoderParameter(Encoder.Quality, 50L)) { using (EncoderParameters parameters = new EncoderParameters(1)) { parameters.Param[0] = qualityParameter; ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegCodec = null; foreach (ImageCodecInfo codec in codecs) { if (codec.MimeType == "image/jpeg") { jpegCodec = codec; break; } } using (MemoryStream inStream = new MemoryStream()) { frame.Save(inStream, jpegCodec, parameters); // HUUUGE Memory Leak Byte[] buffer = new Byte[inStream.Length]; inStream.Read(buffer, 0, buffer.Length); using (MemoryStream outStream = new MemoryStream()) { using (GZipStream gzipStream = new GZipStream(outStream, CompressionMode.Compress)) { gzipStream.Write(buffer, 0, buffer.Length); } Byte[] frameData = outStream.ToArray(); Byte[] packet = new Byte[15 + frameData.Length]; Byte[] frameLength = BitConverter.GetBytes(frameData.Length); Array.Copy(frameLength, 0, packet, 0, frameLength.Length); Array.Copy(frameData, 0, packet, 15, frameData.Length); m_Socket.Send(packet); } } } } } 

Le sugiero que ejecute su código en CLR Profiler para localizar la fuente de la fuga. Si se trata de un objeto administrado de cualquier tipo (incluso un recurso no administrado), siempre que el error no se deba a un tipo administrado con fugas en un manejador no administrado, podrá ver dónde está la fuga. Si está en el código del marco, es probable que pueda solucionarlo utilizando la reflexión y P / Invoke.

Por ejemplo, el tipo de Icon HICON Win32 HICON s en algunas circunstancias. La solución para esto es disponer manualmente el HICON mediante el uso de la función DeleteObject , utilizando el controlador expuesto por el Icon .

Está bien, después de probar ideas y pensamientos de todos y muchos otros métodos. Finalmente probé lo simple:

 using (frame) { frame.Save(outStream, jpegCodec, parameters); } 

Y bueno, esto funcionó y la pérdida de memoria está arreglada. Intenté invocar al recolector de basura de forma forzosa, eliminando el bitmap manualmente, usando P / Invoke DeleteObject, nada funcionó, pero el uso de una instrucción using lo hizo. Así que esto me hace preguntarme qué sucede debajo de una statement de uso que me estoy perdiendo …

Debe establecer el bitmap en nulo cuando termine de trabajar con él, después de la eliminación.

Además, es posible que desee invocar el recolector de basura después de la eliminación del bitmap (aunque sea una operación costosa): GC.Collect();

El bitmap contiene recursos no administrados: el GC no siempre está “en la bola” con estos. Aquí hay un enlace interesante con respecto a la clase Bitmap (desde la perspectiva del marco compacto): http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx

No sé mucho acerca de sockets. Sin embargo, sé que una forma de detener una pérdida de memoria con la clase Imagen es congelar el bitmap. Con suerte, esta publicación podría proporcionarle más información. ¿Podría el MemoryStream.Dispose estar fallando? Por lo tanto, creando una pérdida de memoria.

¿Está llamando al método .Dispose () de su objeto Graphics? Eso causará una pérdida de memoria. EDITAR: Una vez que haya escrito el byte [], ahora puede borrar .Dispose () del objeto Bitmap.