Dans quels scénarios le gel des objects WPF améliore-t-il considérablement les performances?

De nombreux types dans WPF dérivent de Freezable . Il fournit l’immuabilité aux objects POCO mutables et, apparemment, permet d’améliorer les performances dans certaines situations.

Quelqu’un at-il trouvé que la congélation d’objects dans leur application WPF a considérablement amélioré les performances? Si oui, alors quels articles ont donné la plus grande différence de performance lorsqu’ils ont été gelés?

(Notez que j’ai posté une question similaire mais différente )

Vous pourriez être intéressé par mes expériences avec Freezable:

J’ai déjà écrit un lecteur PDF en utilisant muPdf qui rend les bitmaps, que je rend avec WPF. Ce qui aide énormément les performances, c’est que je peux rendre les bitmaps de page sur un thread d’arrière-plan, les geler, puis les transmettre au thread d’interface utilisateur. Il est bon que WPF ne copie pas l’image pour la geler, mais la possibilité de faire toute cette préparation sur un thread d’arrière-plan était le principal avantage pour moi.

D’après ce que j’ai compris, tous les éléments visuels doivent être gelés pour pouvoir être rendus en toute sécurité par le thread de rendu WPF. Si vous restituez de grands visuels non gelés, ils seront clonés sur ceux qui sont gelés lorsque WPF les affiche. Si vous gelez vos bitmaps statiques au préalable, WPF peut simplement partager le pointeur avec le thread de rendu sans cloner. Les objects non figés peuvent même être copiés à plusieurs resockets si WPF ne sait pas si l’object a été modifié depuis la dernière fois qu’il a été rendu. Les objects gelés éliminent le besoin de toute cette copie.

Ces memory leaks potentielles peuvent se produire si vous utilisez le contrôle Image (et non la méthode Freeze):

a) Vous utilisez BitmapImage comme source d’image et ne publiez pas 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) Vous affectez plusieurs BitmapImage comme source d’image et ne libérez pas la totalité de BitmapImage que vous avez utilisée (similaire à (a)). Celui-ci introduit dans .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); 

Source: Performance de WPF

Bien que vous ayez déjà accepté la réponse, je voulais simplement consigner une version différente de la réponse qui m’a aidé.

De MSDN (modification mineure):

Si vous deviez modifier la référence du contrôle aux ressources de bas niveau non gérées (par exemple: Brush), chaque modification devrait régénérer ces objects de bas niveau!

La classe freezable permet à un pinceau de trouver ses objects de bas niveau générés et de les mettre à jour quand il change. Lorsque cette capacité est activée, le pinceau est dit “dégelé”.

La méthode Freeze d’un gel vous permet de désactiver cette fonctionnalité de mise à jour automatique. Vous pouvez utiliser cette méthode pour rendre la brosse «gelée» ou non modifiable. Ainsi, améliorer les performances.

Et, le code pour expliquer l’utilisation:

  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; } 

J’ai développé une application de visualisation d’images performante. Nous avions du code sur le back-end qui créait un nouveau bitmap à chaque image et écrivait ce bitmap à l’écran comme suit:

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

Au cours des tests, nous avons remarqué un scintillement terrible lors de l’utilisation de 30+ FPS avec des images de taille moyenne (1080p). Le correctif? Il suffit de geler le bitmap avant de le définir sur l’image.Source. Plus de bogue de performance qui tue les produits. Aujourd’hui, j’essaye de geler tout ce que je peux.