2009-04-28 38 views

回答

43

您可能会感兴趣我的经验与可冻结:

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

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

+0

非常有帮助谢谢。我没有意识到你可以在后台线程上做到这一点,应该帮助我的一个应用程序相当大! – Kelly 2017-05-19 00:00:00

16

如果使用Image控件(而不是用冷冻法)这些潜在的内存泄漏可能发生:

一)使用的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 Performance

+0

我假设你指的是这里描述的情况:https://blogs.msdn.microsoft.com/jgoldb/2008/02/04/finding-memory-leaks-in-wpf-based-applications/(你应该把你的答案中的具体链接)。我认为值得指出的是,在这些场景中冻结位图只是解决从根本上被认为是坏主意的方法,即使用“静态”字段来存储随后的位图在一个`Image`对象中引用。 – 2016-09-26 00:17:31

+0

`Image`对象必须订阅更改事件,因此位图保留了强引用,阻止了`Image`的GC,当然还有任何订阅了_its_更改事件的GC。这实际上是一个更广泛的问题,编写事件驱动代码的人需要注意:如果这些对象是由事件字段间接引用的,则“static”字段可以对整个对象树进行根。冻结位图有其他原因,但更好的解决方法是在不再需要位图对象的时候(例如关闭窗口时)不要在静态字段中放置位图对象。 – 2016-09-26 00:17:35

12

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

MSDN(次要编辑):

如果你要修改的控制保持基准非托管的低级别资源(例如:刷),每次修改将不得不重新生成这些低级别的对象!

冻结类是什么让刷子的能力 找到其相应的生成的低级别的对象,并更新 他们改变时。当这种能力被启用时,画笔被称为 被“解冻”。

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

而且,代码解释用法:

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

我公司开发的高性能图像浏览器应用。我们对创建一个新的位图每帧后端代码,并写道,位图到屏幕上,像这样:

Writeablebitmap wb = new WriteableBitmap(); 
// < code to set the wb pixel values here > 

// Push the bitmap to the screen 
image.Source = wb; 

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

相关问题