15 consejos de rendimiento de WPF
¿Es usted un desarrollador de WPF? Aquí te presentamos 15 consejos para ayudarte a identificar y mejorar el rendimiento de tus aplicaciones WPF. Leer más.
¿Es usted un desarrollador de WPF? ¿Las aplicaciones de WPF tienen áreas de rendimiento deficiente o no se ejecutan tan rápido como le gustaría? Si es así, tengo 15 consejos para ayudarle a identificar y mejorar el rendimiento de sus aplicaciones de WPF.
Aunque WPF tiene más de una década de antigüedad y se ha mejorado mucho a lo largo de los años, todavía hay varias áreas que pueden sufrir un rendimiento deficiente. Las razones de este bajo rendimiento incluyen cosas como malas prácticas de codificación, enlaces rotos, diseños complejos, falta de virtualización de la interfaz de usuario y mucho más. Afortunadamente, con un poco de planeación y una sólida comprensión de la plataforma WPF, puede hacer que sus aplicaciones de WPF salten a la velocidad de la deformación y salten por el universo en milisegundos.
He reunido estos 15 consejos para ayudarle a mejorar el rendimiento de sus aplicaciones WPF.
1. Simplifica tu árbol visual
Una fuente común de problemas de rendimiento es un diseño profundo y complejo. Mantén el marcado XAML lo más sencillo y superficial posible.Cuando los elementos de la interfaz de usuario se dibujan en la pantalla, se llama a un "paso de diseño" dos veces para cada elemento (un paso de medida y un paso de organización). Elpaso de diseño es un proceso matemático intensivo: cuanto mayor sea el número deelementos secundariosen elelemento, mayor será el número de cálculos necesarios.
2. Virtualice sus ItemsControls
Como se mencionó anteriormente, un árbol visual complejo y profundo da como resultado una mayor huella de memoria y un rendimiento más lento. ItemsControls suele aumentar los problemas de rendimiento con árboles visuales profundos porque no están virtualizados. Esto significa que se crean y destruyen constantemente para cada elemento del control. En su lugar, use VirtualizingStackPanel como host de elementos y use VirtualizingStackPanel.IsVirtualizing y establezca VirtualizationMode en Recycling para reutilizar los contenedores de elementos en lugar de crear otros nuevos cada vez.
3. Favorezca los recursos estáticos sobre los recursos dinámicos
StaticResources proporciona valores para cualquier atributo de propiedad XAML mediante la búsqueda de una referencia a un recurso ya definido. El comportamiento de búsqueda de ese recurso es el mismo que el de una búsqueda en tiempo de compilación. DynamicResources creará una expresión temporal y aplazará la búsqueda de recursos hasta que se requiera el valor de recurso solicitado. El comportamiento de búsqueda de ese recurso es el mismo que el de una búsqueda en tiempo de ejecución, lo que impone un impacto en el rendimiento. Utilice siempre que sea posible, StaticResource.
4. Opacidad en pinceles en lugar de elementos
Si utiliza un pincel para establecer el relleno o el trazo de un elemento, es mejor establecer la opacidad en el pincel en lugar de establecer la propiedad opacidad del elemento. Al modificar la propiedad Opacity de un elemento, WPF puede crear superficies temporales, lo que da lugar a un impacto en el rendimiento.
5. Avoid Using Run to Set Text Properties
Evite usar Runs dentro de un TextBlock, ya que esto da como resultado una operación intensiva de rendimiento mucho mayor. Si usa Run para establecer propiedades de texto, establézcalas directamente en TextBlock en su lugar.
6. Favor StreamGeometries over PathGeometries
El objeto StreamGeometry es una alternativa muy ligera a PathGeometry. StreamGeometry está optimizado para manejar muchos objetos PathGeometry. Consume menos memoria y funciona mucho mejor en comparación con el uso de muchos objetos PathGeometry.
7. Use Reduced Image Sizes
Si tu app requiere la visualización de miniaturas más pequeñas, considera la posibilidad de crear versiones de tamaño reducido de tus imágenes. De forma predeterminada, WPF cargará y descodificará la imagen a su tamaño completo. Esto puede ser el origen de muchos problemas de rendimiento si se cargan imágenes completas y se reducen verticalmente a tamaños de miniatura en controles como ItemsControl. Si es posible, combine todas las imágenes en una sola imagen, como una tira de película compuesta por varias imágenes.
8. Lower the BitMapScalingMode
De forma predeterminada, WPF usa un algoritmo de remuestreo de imágenes de alta calidad que a veces puede consumir recursos del sistema, lo que da lugar a una degradación de la velocidad de fotogramas y hace que las animaciones tartamudeen. En su lugar, establezca BitMapScalingMode en LowQuality para cambiar de un algoritmo de "calidad optimizada" a un algoritmo de "velocidad optimizada".
9. Usar y congelar congelables
Un objeto congelable es un tipo especial de objeto que tiene dos estados: descongelado y congelado. Al inmovilizar un objeto, como un pincel o una geometría, ya no se puede modificar. Congelar objetos siempre que sea posible mejora el rendimiento de la aplicación y reduce su consumo de memoria.
10. Fix your Binding Errors
Los errores de enlace son el tipo más común de problema de rendimiento en las aplicaciones de WPF. Cada vez que se produce un error de enlace, la aplicación recibe un impacto de rendimiento y, a medida que intenta resolver el enlace, escribe el error en el registro de seguimiento. Como puedes imaginar, cuantos más errores de enlace tengas, mayor será el impacto en el rendimiento de tu aplicación. Tómese el tiempo necesario para encontrar y corregir todos los errores de enlace. El uso de un enlace RelativeSource en DataTemplates es uno de los principales culpables del error de enlace, ya que normalmente el enlace no se resuelve correctamente hasta que DataTempate ha completado su inicialización. Evite usar RelativeSource.FindAncestor a toda costa. En su lugar, defina una propiedad adjunta y use la herencia de propiedades para insertar valores en el árbol visual en lugar de buscar el árbol visual.
11. Evite el enlace de datos a la propiedad Label.Content
Si usa un enlace Label to data a una propiedad String, esto dará lugar a un rendimiento deficiente. Esto se debe a que cada vez que se actualiza el origen de String, se descarta el objeto de cadena antiguo y se crea una nueva String. Si el contenido de la etiqueta es texto simple, reemplácelo por un TextBlock y enlace a la propiedad Text en su lugar.
12. Bind ItemsControls to IList instead of IEnumerable
Al enlazar datos de un ItemsControl a un IEnumerable, WPF creará un contenedor de tipo IList<T> que afecta negativamente al rendimiento con la creación de un segundo objeto. En su lugar, enlaza ItemsControl directamente a un IList para evitar la sobrecarga del objeto contenedor.
13. Use the NeutralResourcesLanguage Attribute
Use NeutralResourcesLanguageAttribute para indicar a ResourceManager cuál es la referencia cultural neutra y evitar búsquedas incorrectas de ensamblados satélite.
14. Cargar datos en subprocesos separados
Una fuente muy común de problemas de rendimiento, bloqueos de la interfaz de usuario y aplicaciones que dejan de responder es la forma en que carga sus datos. Asegúrese de cargar los datos de forma asincrónica en un subproceso independiente para no sobrecargar el subproceso de la interfaz de usuario. La carga de datos en el subproceso de la interfaz de usuario dará como resultado un rendimiento muy deficiente y una mala experiencia general del usuario final. El subprocesamiento múltiple debe ser algo que todos los desarrolladores de WPF usen en sus aplicaciones.
15. Beware of Memory Leaks
Las pérdidas de memoria son la causa número uno de problemas de rendimiento en la mayoría de las aplicaciones de WPF. Son fáciles de tener, pero pueden ser difíciles de encontrar. Por ejemplo, el uso de DependencyPropertyDescriptor.AddValueChanged puede hacer que el marco de WPF tome una referencia segura al origen del evento que no se quita hasta que se llama manualmente a DependencyPropertyDescriptor.RemoveValueChanged. Si tus vistas o comportamientos dependen de eventos que se generan desde un objeto o ViewModel (como INotifyPropertyChanged), suscríbete a ellos de manera débil o asegúrate de cancelar la suscripción manualmente. Además, si enlazas a propiedades en un ViewModel que no implementa INotifyPropertyChanged, es probable que tengas una pérdida de memoria.
Por último, un consejo extra. A veces, cuando tiene un problema de rendimiento, puede ser muy difícil identificar qué es exactamente lo que está causando el problema. Sugiero usar un generador de perfiles de rendimiento de aplicaciones para ayudar a identificar dónde se producen estos cuellos de botella de rendimiento en la base de código. Hay muchas opciones de generador de perfiles disponibles para usted. Algunos son de pago y otros son gratuitos. La que más utilizo personalmente son las herramientas de diagnóstico integradas directamente en Visual Studio 2019.
Asegúrate de interactuar conmigo en Twitter, suscríbete a mi canal de YouTube para recibir notificaciones de nuevos contenidos de video y sígueme en Twitch para verme transmitir en vivo. Y si está utilizando Ultimate UI for WPF, asegúrese de conectarse con nuestros diversos equipos a través de nuestros foros de la comunidad, donde puede interactuar con ingenieros Infragistics y otros clientes.