WPF中的许多类型派生自Freezable
。它为可变POCO对象提供了不变性,显然可以在某些情况下提高性能。
有没有人发现WPF应用程序中的冻结对象大大提高了性能?如果是这样,那么哪些项目在冻结时会产生最大的性能差异?
(请注意,我也发布了similar but different question)
答案 0 :(得分:51)
您可能对我使用Freezable的经历感兴趣:
我曾经使用muPdf编写了一个PDF查看器,它渲染了我用WPF渲染的位图。有助于提高性能的是我可以在后台线程上呈现页面位图,冻结它们,然后将它们传递给UI线程。 WPF不会复制图像以冻结它是很好的,但是在后台线程上完成所有这些准备的能力对我来说是关键的好处。
据我了解,所有视觉效果都需要冻结,以便WPF渲染线程可以安全地呈现它们。如果渲染大量未冻结的视觉效果,当WPF呈现它们时,它们将被克隆到冻结的视觉效果中。如果事先冻结静态位图,WPF只能与渲染线程共享指针而不进行克隆。如果WPF不知道对象是否从上次渲染时更改,则未冻结的对象甚至可能会被重复复制。冻结的对象消除了所有这些复制的需要。
答案 1 :(得分:18)
如果使用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);
答案 2 :(得分:13)
虽然你已经接受了答案,但只是想记录一个不同版本的答案,这对我帮助更大。
来自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;
}
答案 3 :(得分:4)
我开发了一个高性能的图像查看器应用程序。我们在后端有代码,每帧都创建一个新的位图,并将该位图写入屏幕,如下所示:
Writeablebitmap wb = new WriteableBitmap();
// < code to set the wb pixel values here >
// Push the bitmap to the screen
image.Source = wb;
在测试过程中,我们发现在使用中等大小的图像(1080p)拍摄30+ FPS时会出现可怕的闪烁现象。修复?只需冻结位图,然后再将其设置为image.Source。没有更多的产品杀死性能错误。现在我试着冻结我所能做的一切。