2011-07-08 18 views
7

Necesito cargar dinámicamente muchas (a veces cientos) de imágenes en miniatura. Por razones de rendimiento, debo hacer esto en un número limitado de solicitudes, estoy usando una sola solicitud/respuesta para las pruebas. Enviaré los datos binarios para las imágenes en la respuesta y las cargaré en BitmapImage utilizando un MemoryStream. Esto funciona correctamente hasta que cargue más de aproximadamente 80 miniaturas, luego obtengo la excepción de falla catastrófica. Para asegurarme de que mis datos no estaban corruptos, traté de cargar una imagen de mapa de bits varias veces con la misma matriz de bytes y se bloquea después de aproximadamente 80 cargas.Silverlight: BitmapImage from stream throws exception (Error catastrófico (Excepción de HRESULT: 0x8000FFFF (E_UNEXPECTED)))

Este es un ejemplo de cómo la imagen se carga desde la matriz de bytes, la matriz de bytes se sabe que tiene datos de imagen válidos (PNG):

private BitmapImage LoadImage(byte[] imageData) 
{ 
    BitmapImage img = new BitmapImage(); 
    MemoryStream stream = new MemoryStream(imageData); 
    img.SetSource(stream); // Exception thrown here after too many images loaded. 
    return img; 
} 

entonces utilizo el BitmapImage como fuente para una Elemento de imagen en la página, pero el error ocurre en la línea img.SetSource(...) arriba.

Al agregar GC.Collect() al bucle donde estoy cargando imágenes en miniatura, me permite cargar algunas imágenes más, así que estoy pensando que esto tiene algo que ver con la administración de memoria, pero no sé qué puedo hacer para solucionar el problema .

+0

no estoy seguro de si esto podría ser el problema, pero sí que tiene MemoryStream ReadTimeout y WriteTimeout propiedades. ¿Podría la transmisión ser el tiempo de espera? – Danexxtone

+0

Intenté configurar ReadTimeout y obtuve una excepción: los tiempos de espera no son compatibles con esta secuencia. – toby

+0

¿Puedes aclarar algunas cosas: por qué una matriz de bytes? ¿No hay una transmisión de la descarga que pueda enviar a 'img.SetSource' directamente?¿Está seguro de que los pngs que se están descargando son de tamaño "miniatura" o está descargando imágenes más grandes que están siendo escaladas por el control de imagen? ¿Son estas miniaturas de fotos? – AnthonyWJones

Respuesta

6

Creo que citar la respuesta que proporciona por Microsoft en el informe de error anterior es que vale la pena ya que es muy breve y descriptivo del problema, así como proporcionar una solución recomendada:

Cuando Silverlight se carga una imagen, la el marco mantiene una referencia y guarda en caché la imagen decodificada hasta que se devuelve el control de flujo al despachador de hilos de la interfaz de usuario. Cuando carga imágenes en un circuito cerrado como ese, aunque su aplicación no conserve una referencia, el GC no puede liberar la imagen hasta que liberemos nuestra referencia cuando se devuelva el control de flujo.

Después de procesar unas 20 imágenes, puede detener y poner en cola el siguiente conjunto utilizando Dispatcher.BeginInvoke solo para dividir el trabajo que se procesa en un lote. Esto nos permitirá liberar imágenes que su aplicación no retiene.

entiendo con el comportamiento de descodificación actual no es obvio que Silverlight está reteniendo estas referencias, pero cambiando el diseño de decodificador podría afectar otras áreas, así que por ahora te recomiendo el tratamiento de imágenes como esta en lotes.

Ahora, si realmente está tratando de cargar 500 imágenes y retenerlas, es probable que se quede sin memoria según el tamaño de la imagen. Si está tratando con un documento de varias páginas, puede cargar páginas en demanda en segundo plano y liberarlas cuando no se ven con algunas páginas de memoria intermedia, de modo que en ningún momento exceda los límites razonables de memoria de textura.

Cuestiones relacionadas