wpf performance freeze freezable

¿En qué escenarios el congelamiento de objetos WPF beneficia en gran medida el rendimiento?



performance freeze (4)

Aunque ya ha aceptado la respuesta, solo quería registrar una versión diferente de la respuesta que me ayudó a mejorar.

Desde MSDN (edición menor):

Si tuviera que modificar la referencia de retención de control a los recursos de bajo nivel no administrados (por ejemplo: Pincel), ¡cada modificación tendría que regenerar esos objetos de bajo nivel!

La clase freezable es lo que le da a un pincel la capacidad de encontrar sus correspondientes objetos generados de bajo nivel y actualizarlos cuando cambia. Cuando esta habilidad está habilitada, se dice que el cepillo está "descongelado".

El método Freeze de Freezable le permite desactivar esta capacidad de actualización automática. Puede usar este método para hacer que el pincel se "congele" o no se pueda modificar. Por lo tanto, mejorar el rendimiento.

Y el código para explicar el uso:

Button myButton = new Button(); SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow); if (myBrush.CanFreeze) { // Makes the brush unmodifiable. myBrush.Freeze(); } myButton.Background = myBrush; if (myBrush.IsFrozen) // Evaluates to true. { // If the brush is frozen, create a clone and modify the clone. SolidColorBrush myBrushClone = myBrush.Clone(); myBrushClone.Color = Colors.Red; myButton.Background = myBrushClone; } else { // If the brush is not frozen, it can be modified directly. myBrush.Color = Colors.Red; }

Muchos tipos en WPF derivan de Freezable . Proporciona inmutabilidad a objetos POCO mutables y, aparentemente, permite un mejor rendimiento en ciertas situaciones.

¿Alguien ha encontrado que congelar objetos dentro de su aplicación WPF ha mejorado mucho el rendimiento? Si es así, ¿qué elementos dieron la mayor diferencia de rendimiento cuando se congelaron?

(Tenga en cuenta que también he publicado una pregunta similar pero diferente )


Desarrollé una aplicación de visor de imágenes de alto rendimiento. Teníamos código en el back-end que creaba un nuevo mapa de bits en cada fotograma y escribíamos ese mapa de bits en la pantalla de la siguiente manera:

Writeablebitmap wb = new WriteableBitmap(); // < code to set the wb pixel values here > // Push the bitmap to the screen image.Source = wb;

Durante las pruebas, notamos que había un parpadeo terrible mientras se pasaban 30+ FPS con imágenes de tamaño moderado (1080p). ¿La solución? Simplemente inmovilice el mapa de bits antes de configurarlo en la imagen. Fuente. No más errores de rendimiento que matan los productos. Hoy trato de congelar todo lo que puedo.


Estas posibles pérdidas de memoria podrían ocurrir si usa el control de imagen (y no usa el método de congelación):

a) Utiliza BitmapImage como origen de la imagen y no lanza BitmapImage:

static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",UriKind.RelativeOrAbsolute)); m_Image1 = new Image(); m_Image1.Source = bi1; //bi1.Freeze() //if you do not Freeze, your app will leak memory. MyStackPanel.Children.Add(m_Image1);

b) Asigna múltiples imágenes de mapa de bits como origen de la imagen y no libera todo el mapa de bits que utilizó (similar a (a)). Este introducido en .Net 3.5:

static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp", UriKind.RelativeOrAbsolute)); static BitmapImage bi2 = new BitmapImage(new Uri("Bitmap2.bmp", UriKind.RelativeOrAbsolute)); bi2.Freeze(); m_Image1 = new Image(); //bi1.Freeze() //even though you are really using bi2 for Image Source, //you also need to Freeze bi1 it to avoid leak m_Image1.Source = bi1; // use un-frozen bitmap, which causes the leak m_Image1.Source = bi2; // use frozen bitmap MyStackPanel.Children.Add(m_Image1);

Fuente: Rendimiento de WPF


Puede que te interesen mis experiencias con Freezable:

Una vez escribí un visor de PDF usando muPdf que representa mapas de bits, que renderizo con WPF. Lo que ayuda mucho al rendimiento es que puedo renderizar los mapas de bits de la página en un hilo de fondo, congelarlos y luego pasarlos al hilo de UI. Es bueno que WPF no copie la imagen para congelarla, pero la capacidad de hacer toda esta preparación en un hilo de fondo fue el beneficio clave para mí.

Por lo que entiendo, todas las imágenes deben congelarse para que puedan ser procesadas de forma segura por el hilo de renderizado de WPF. Si renderiza grandes imágenes no congeladas, se clonarán a las congeladas cuando WPF las represente. Si congela sus mapas de bits estáticos de antemano, WPF solo puede compartir el puntero con el subproceso sin clonar. Los objetos no congelados pueden incluso copiarse repetidamente si WPF no sabe si el objeto ha cambiado desde la última vez que se procesó. Los objetos congelados eliminan la necesidad de toda esta copia.