在什么情况下冻结WPF对象大大有利于性能?

WPF中的许多types都来自Freezable 。 它为可变的POCO对象提供了不变性,并且显然允许在某些情况下提高性能。

有没有人发现,冻结WPF应用程序中的对象已经大大提高了性能? 如果是这样,那么哪个项目在冻结时最大的性能差异?

(请注意,我也发布了一个类似但不同的问题 )

你可能会对我有关Freezable的经验感兴趣:

我曾经使用muPdf编写了一个PDF查看器,它呈现了我用WPF呈现的位图。 最重要的是,我可以在后台线程上渲染页面位图,冻结它们,然后将它们传递给UI线程。 WPF不会复制图像来冻结它,但是在后台线程上做所有这些准备的能力对我来说是关键的好处。

据我所知,所有的视觉效果都需要被冻结,以便WPF呈现线程可以安全地呈现它们。 如果您渲染大型的解冻视觉效果,当WPF呈现视觉效果时,它们将被克隆到冻结的视觉效果。 如果您事先冻结您的静态位图,WPF可以与渲染线程共享指针而不克隆。 如果WPF不知道对象是否从上次渲染时发生更改,则反复冻结的对象甚至可能会被重复复制。 冻结的对象消除了所有这些复制的需要。

如果您使用Image控件(而不是使用Freeze方法),则可能会发生这些潜在的内存泄漏:

a)您使用BitmapImage作为图像源,不释放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)您将多个BitmapImage分配为图像源,并且不会释放您使用的所有BitmapImage(类似于(a))。 这个在.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); 

来源: WPF性能

虽然你已经接受了答案,但只是想logging一个不同版本的答案,帮助我更好。

来自MSDN (小编辑):

如果您要修改对非托pipe底层资源(例如:画笔)的引用,每次修改都必须重新生成这些底层对象!

可冻结的类是让画笔能够find其相应的生成的低级对象,并在更改时更新它们。 当这个能力被启用时,画笔被认为是“解冻”的。

Freezable的Freeze方法可以让你禁用这种自我更新的能力。 您可以使用此方法使画笔变得“冻结”或不可修改。 因此,提高性能。

并且,解释用法的代码:

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

我开发了一个高性能的图像查看器应用程序。 我们在后端创build了一个新的位图,并将该位图写入屏幕,如下所示:

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

在testing过程中,我们注意到有一个可怕的闪烁,而30 + FPS与中等大小的图像(1080p)。 修复? 将它设置为图像之前,冻结位图。 没有更多的产品查杀性能错误。 现在我试着冻结一切。

Interesting Posts