¿Cómo liberar la memoria después de que BitmapImage ya no se necesita?

Primero, cargo una BitmapImage en el control de Image en la Window . En segundo lugar, trabajo con el control de Image y luego cierro la Window .

Lo hago 2-3 veces en un minuto y mi memoria se llena muy rápido porque las imágenes no se descargan cuando la ventana está cerrada.

Entonces, ¿cómo descargar BitmapImage desde Image.Source control manualmente para liberar la memoria?

Creo que la solución que está buscando está en http://www.ridgesolutions.ie/index.php/2012/02/03/net-wpf-bitmapimage-file-locking/ . En mi caso, estaba tratando de encontrar una manera de eliminar el archivo después de que se creó, pero parece ser una solución para ambos problemas.

No libera memoria:

 var bitmap = new BitmapImage(new Uri(imageFilePath)); 

Libera memoria y permite que el archivo se elimine:

 var bitmap = new BitmapImage(); var stream = File.OpenRead(imageFilePath); bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.StreamSource = stream; bitmap.EndInit(); stream.Close(); stream.Dispose(); 

Opcionalmente, también congele BitmapImage:

 bitmap.Freeze(); 

En mi situación, parece que el caché de mapas de bits era el problema. Anteriormente estaba cargando bitmaps como este:

 Bitmap bitmap = new Bitmap(); using(var stream = new FileStream(...)) { bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.StreamSource = stream; bitmap.EndInit(); } bitmap.Freeze(); image.Source = bitmap; 

Continuamente reemplazando la imagen. image.Source la misma forma que la memoria acumulada, forzar manualmente la recolección de basura no estaba realmente ayudando.

En cambio, deshabilitar el almacenamiento en caché y hacer que use la transmisión (requiere dejar la ruta abierta hasta que se muestre la imagen) junto con la recolección manual de basura eliminó la acumulación de memoria para mí.

 Stream mediaStream; void DisposeMediaStream() { if (mediaStream != null) { mediaStream.Close(); mediaStream.Dispose(); mediaStream = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true); } } void Update() { DisposeMediaStream(); var bitmap = new BitmapImage(); mediaStream = new FileStream(...); bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.None; bitmap.StreamSource = mediaStream; bitmap.EndInit(); bitmap.Freeze(); ControlImage.Source = bitmap; } 

De esta forma puedo recorrer cientos de imágenes (como Windows Photo Viewer) y la memoria se mantiene baja. Tenga en cuenta que la transmisión no tiene que permanecer abierta una vez que la imagen haya sido procesada.

Puede establecer el objeto como null , de modo que ya no se haga referencia al objeto BitmapImage. En esta situación, el CG debería encargarse de liberar recursos. Puede llamar a GC.Collect pero puede afectar el rendimiento si se usa con demasiada frecuencia.

Puede llamar a Dispose() en las imágenes en el evento Closed la ventana. Creo que también es posible optimizar la huella de tu memoria usando diferentes opciones de almacenamiento en caché.

Editar:

No puede llamar a Dispose (); en su lugar, podría considerar BitmapCacheOption.None . La imagen se leerá directamente desde el disco y no se almacenará en la memoria caché.