2011-10-15 9 views
5

Escribo un código que lee una imagen png del archivo y se muestra con control.
Quiero leer la imagen de la corriente y ajusteexcepción de falta de memoria cuando use control.BackgroundImage = Image.FromStream (memStream);

control.BackgroundImage = Image.FromStream(memStream); 

pero cuando uso este código, se producen "sin memoria" excepción. pero cuando utilice

control.Image = Image.FromStream(memStream); 

o

control.BackgroundImage = Image.FromFile(fileSource); 

, que es el trabajo.

el tamaño del archivo de imagen es de 5KB.

if (System.IO.File.Exists(imgSource)) 
{ 
    using (FileStream localFileStream = new FileStream(imgSource, FileMode.Open)) 
    { 
    using (MemoryStream memStream = new MemoryStream()) 
    { 
    int bytesRead; 
    byte[] buffer = new byte[1024]; 

    while ((bytesRead = localFileStream.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     memStream.Write(buffer, 0, bytesRead); 
    } 
    retIMG = Image.FromStream(memStream); 

    pictureBox1.Image = retIMG;  // is work 
    label1.Image = retIMG;  // is work 
    button1.Image = retIMG;  // is work 
    button1.BackgroundImage = retIMG; // don't work 
    groupBox1.BackgroundImage = retIMG; // don't work 
    panel1.BackgroundImage = retIMG; // don't work 
    } 
    } 
} 

creo que un error en .NET Framework. por favor me ayuda?

+0

¿cuál parte es el problema? Le sugiero que coloque primero la imagen en una variable, luego asigne en la segunda operación. ¿Qué tan grande es la imagen? El tamaño del archivo 5ggb puede ser de 50,000x50,000 píxeles;) – TomTom

+1

Las imágenes informan "Sin memoria" para cualquier cosa que salga mal. –

+0

Al igual que dijo Henk, GDI + (y por lo tanto 'System.Drawing') arroja errores de OutOfMemory en muchos casos donde no está realmente fuera de la memoria, como los parámetros no válidos. Supongo que este es uno de ellos. – CodesInChaos

Respuesta

6

Dando algunos antecedentes para agregar a la respuesta correcta de DeCaf. GDI + se esfuerza mucho para evitar copiar los píxeles de un mapa de bits. Eso es costoso, los mapas de bits que toman docenas de megabytes no son inusuales. Cuando carga un mapa de bits desde un archivo con el constructor de mapa de bits o Image.FromFile() entonces GDI + crea un archivo mapeado en la memoria. Los píxeles son paginados a petición, solo cuando sea necesario. Muy eficiente, pero bloquea el archivo. Claramente, estabas tratando de evitar eso encerrado en este código.

De hecho, evita ese bloqueo cargando los bytes en la memoria usted mismo con un MemoryStream. Pero el mismo principio todavía se aplica, GDI + todavía no copia los píxeles y solo lee de la transmisión cuando es necesario. Esto falla cuando desecha() la transmisión. Muy difícil de diagnosticar porque se produce la excepción posterior, normalmente cuando se debe dibujar el mapa de bits. Se bombardea en el código de pintura, no tiene ningún código para mirar, pero Application.Run(). Con un mensaje de excepción horrible, GDI + solo tiene un puñado de códigos de error. Usted es no sin memoria, solo se ve de esa manera a GDI +, de lo contrario no puede entender por qué la transmisión ya no es legible.

Al menos parte del problema se debe a la muy incómoda implementación de MemoryStream.Dispose(). Dispose está destinado a liberar recursos no administrados. Un flujo de memoria no tiene ninguno, solo posee memoria.Eso ya está solucionado por el recolector de basura. Lamentablemente lo implementaron de todos modos. No desechando nada, ya que no hay nada que desechar, pero marcando el MemoryStream como ilegible. Lo cual activa el error en GDI + cuando intenta leer mientras dibuja el mapa de bits.

Así que simplemente elimine el usando la instrucción para evitar deshacerse del MemoryStream para solucionar su problema. Y no se preocupe por deshacerse de él más tarde cuando el mapa de bits ya no esté en uso. No hay nada que desechar, el recolector de basura libera automáticamente la memoria.

+0

En realidad, el 'MemoryStream' puede contener recursos no administrados en forma de un' WaitHandle', es decir, si se invoca 'BeginRead' o 'BeginWrite'. Es poco probable que sea un problema aquí, pero pensé que debería señalarlo de todos modos. – DeCaf

+0

cierto. De hecho poco probable. –

+1

+1 por una bonita explicación de antecedentes por cierto! – DeCaf

7

Leer las observaciones sobre Image.FromStream en MSDN:

debe mantener el flujo abierto durante toda la vida de la Imagen.

Así que si se quita el using en torno a la creación de su MemoryStream su código funciona bien.

Por supuesto debe disponer preferentemente el MemoryStream una vez que ya no necesita el Image que ha creado, aunque no es probable que ningún daño en este caso de no llamar Dispose() y dejando a la GC para recoger una vez utilizada.

El hecho de que parezca funcionar con algunos de sus códigos probablemente sea pura suerte y no debe considerarse una solución funcional. Siempre lea la documentación para averiguar sobre peculiaridades como esta.

Cuestiones relacionadas