WPF中的许多类型都源于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指定为Image源,并且不释放您使用的所有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表演
虽然你已经接受了答案,但只是想记录一个不同版本的答案,这些答案对我有所帮助.
来自MSDN(次要编辑):
如果要修改对非托管低级资源(例如:Brush)的控制保持引用,则每次修改都必须重新生成那些低级对象!
freezable类使刷子能够找到相应的生成的低级对象,并在更改时更新它们.启用此功能后,刷子会被称为"解冻".
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; }