new fromfile create compact-framework gdi+ bitmap

compact framework - fromfile - OutOfMemoryException al crear un mapa de bits grande en CF.NET



new bitmap image c# (4)

Mi aplicación de marco compacto crea una lista de desplazamiento suave al representar todos los elementos en una superficie de mapa de bits grande, y luego copiar ese mapa de bits a una posición de desplazamiento en la pantalla para que solo se muestren los elementos apropiados. Las versiones anteriores solo mostraban los elementos que deberían aparecer en la pantalla en ese momento, pero este enfoque era demasiado lento para una interfaz de desplazamiento suave.

Ocasionalmente genera una excepción OutOfMemoryException al crear inicialmente el mapa de bits grande. Si el usuario realiza un reinicio por software del dispositivo y ejecuta nuevamente la aplicación, puede realizar la creación sin problemas.

No parece que este mapa de bits se esté generando en la memoria de programa, ya que la aplicación utiliza aproximadamente la misma cantidad de memoria de programa que antes de los nuevos métodos de desplazamiento suave.

¿Hay alguna manera de evitar esta excepción? ¿Hay alguna manera de liberar la memoria que necesito (donde sea que esté) antes de lanzar la excepción?


Como parece que se ha topado con una limitación del dispositivo que restringe el tamaño total del espacio de mapa de bits que puede crear (aparentemente se crean en RAM de video en lugar de en la memoria general del programa), una alternativa es reemplazar el objeto de mapa de bits utilizado aquí. un bloque antiguo de la memoria de Windows, accediendo a él para leer y escribir mediante Invocar la función BitBlt API.

Inicialmente, crear el bloque de memoria es complicado, y probablemente quiera hacer otra pregunta sobre eso (GCHandle.Alloc puede usarse aquí para crear un objeto "pinned", lo que significa que .NET no puede moverlo en memoria, que es crítica aquí). Sé cómo hacerlo, pero no estoy seguro de hacerlo correctamente y prefiero contar con la opinión de un experto.

Una vez que haya creado el bloque grande, iterará a través de sus elementos, renderizará cada uno en un pequeño mapa de bits que siga utilizando (usando su código .NET existente) y lo transferirá al lugar apropiado en su bloque de memoria.

Después de crear todo el caché, su código de representación debería funcionar igual que antes, con la diferencia de que, en lugar de copiar desde el mapa de bits grande a su superficie de representación, BitBlt desde el bloque de caché. Los argumentos para BitBlt son esencialmente los mismos que para DrawImage (destino, fuente, coordenadas y tamaños, etc.).

Como está creando la caché de la memoria normal de esta manera en lugar de la RAM de video especializada, no creo que se encuentre con el mismo problema. Sin embargo, definitivamente conseguiría que el código de creación de bloques funcione primero y la prueba para asegurarme de que pueda crear un bloque lo suficientemente grande en todo momento.

Actualización: en realidad, el enfoque ideal sería tener una colección de bloques de memoria más pequeños en lugar de uno grande (como pensé que era el problema con el enfoque de mapa de bits), pero ya tienes suficiente para hacer. He trabajado con aplicaciones de CF que se ocupan de objetos de 5 y 10MB y, de todos modos, no es un gran problema (aunque podría ser un problema mayor cuando ese trozo está inmovilizado, no lo sé). Por cierto, siempre me han sorprendido los OOMEs en la creación de BitMap porque sabía que los mapas de bits eran mucho más pequeños que la memoria disponible, como tú ... ahora sé por qué. Lo siento, pensé que esto era una solución fácil al principio.


Su mapa de bits definitivamente se está creando en la memoria del programa. La cantidad de memoria que necesita el mapa de bits depende de cuán grande sea, y si este tamaño requerido generará OutOfMemoryException depende de cuánto está disponible para el PDA (lo que hace que este sea un error aleatorio).

Lo sentimos, pero esta es generalmente una técnica de representación de control desaconsejable (especialmente en el Framework Compacto) para la cual no hay ninguna solución que no sea aumentar la memoria física en el PDA, que generalmente no es posible (y con frecuencia no solucionará el problema de todos modos , ya que un proceso de CF está limitado a 32 MB, sin importar cuánto tenga disponible el dispositivo).

Su mejor opción es volver a la versión anterior y mejorar su velocidad de representación. También hay una técnica simple disponible en CF para hacer un control de doble buffer para eliminar el parpadeo.


Sugiero volver al viejo mecanismo de renderizar solo una parte de los datos, ya que el tamaño de los datos completamente renderizados es obviamente un problema. Para ayudar a prevenir problemas de renderizado, probablemente renderice algunas filas arriba y abajo de la vista actual para que puedan "desplazarse" con un impacto limitado.


Y tan pronto como lo publique, pensé en algo que puede hacer para solucionar su problema con la nueva versión. El problema que tiene es que CF está tratando de encontrar un bloque de memoria contigua disponible para el gran mapa de bits, y esto ocasionalmente es un problema.

En lugar de crear un mapa de bits grande, puede crear una colección de mapas de bits más pequeños, uno para cada elemento, y representar cada elemento en su propio mapa de bits pequeño. Durante la visualización, simplemente copie los mapas de bits que necesita. A CF le resultará mucho más fácil crear un montón de pequeños mapas de bits que uno grande, y no debería tener ningún problema de memoria a menos que se trate de un enorme grupo de elementos.

Debería evitar expresiones como "no hay solución".

Otro punto importante: asegúrese de llamar a Dispose () en cada mapa de bits cuando haya terminado con él.