WriteableBitmap内存泄漏? [英] WriteableBitmap Memory Leak?

查看:215
本文介绍了WriteableBitmap内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码基于UI元素创建实时图块. 它将uiElement呈现在WriteableBitmap上,保存位图+返回文件名. 此方法在Windows Phone后台任务代理中运行,并且我遇到内存限制.

i am using the code below to create a live tile, based on an UI element. It renders the uiElement on a WriteableBitmap, saves the bitmap + returns the filename. This method is run in a windows phone background task agent an i am running into memory limits.

private string CreateLiveTileImage(Canvas uiElement, int width, int heigth)
{
   var wbmp = new WriteableBitmap(width, heigth);
   try
   {
      wbmp.Render(uiElement, null);
      wbmp.Invalidate();

      var tileImageName = _liveTileStoreLocation;
      using (var stream = new IsolatedStorageFileStream(tileImageName, FileMode.Create, FileAccess.Write, IsolatedStorageFile.GetUserStoreForApplication()))
      {
         wbmp.SaveJpeg(stream, width, heigth, 0, 100);
         stream.Close();
      }

      uiElement = null;
      wbmp = null;
      GC.Collect();
      return "isostore:" + tileImageName;
   }
   catch (Exception exception)
   {
      // ...
   }
   return null;
}

我做了一些测试,问题是:这种方法会泄漏内存,但我不知道 为什么/在哪里?!

I did some testing and the problem is: This methods leaks memory, but i do not know why/where?!

我还进行了一些测试-在首次使用此方法之前:

I also did some test runs - before first run into this method:

Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
7.249.920 Bytes

没关系,因为已连接调试器,该调试器使用大约2 MB的内存.

This is ok, since the debugger is attached, which uses about 2 MB memory.

对此方法进行更多运行(在调试器中再次设置为再次运行方法):

Doing some more runs of this method (set back to run method again in debugger):

Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
8851456  long +  40960
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
8892416  long + 245760
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9138176  long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9281536  long + 151552
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9433088  long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9576448  long + 139264
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9715712  long + 139264
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9859072  long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
10006528 long + 147456

因此,此方法使用的内存会增加.

So the memory, used by this method increases.

但是为什么呢? 我认为没有引用可以阻止收集对象.

But why? In my opinion there are no references that prevent the objects from getting collected.

2013年4月5日更新

感谢您的所有回答! 如建议的那样,我减少了代码,最终可以用几行代码重现该问题.

thank you for all your answers! As suggested, i reduced the code + finnally was able to reproduce the problem in a few lines of code.

void Main()
{
   for (int i = 0; i < 100; i++)
   {
      CreateImage();
   }
}

private void CreateImage()
{
   var rectangle = CreateRectangle();
   var writeableBitmap = new WriteableBitmap(rectangle, rectangle.RenderTransform);

   rectangle = null;
   writeableBitmap = null;
   GC.Collect();
}

private Rectangle CreateRectangle()
{
   var solidColorBrush = new SolidColorBrush(Colors.Blue);
   var rectangle = new Rectangle
   {
   Width = 1000,
   Height = 1000,
   Fill = solidColorBrush  // !!! THIS causes that the image writeableBitmap never gets garbage collected
   };

   return rectangle;
}

启动应用程序后:ApplicationCurrentMemory用法:"11681792字节"

After starting the App: ApplicationCurrentMemoryUsage: "11 681 792 Bytes"

1次迭代-ApplicationCurrentMemory使用情况:"28 090 368字节"

1 Iteration - ApplicationCurrentMemoryUsage: "28 090 368 Bytes"

5次迭代-ApplicationCurrentMemory使用情况:"77 111 296字节"

5 Iterations - ApplicationCurrentMemoryUsage: "77 111 296 Bytes"

20次迭代-ApplicationCurrentMemory使用情况:"260 378 624字节"

20 Iterations - ApplicationCurrentMemoryUsage: "260 378 624 Bytes"

23个迭代之后:内存不足异常. Ln .: var writeableBitmap = new WriteableBitmap(rectangle,rectangle.RenderTransform);

After 23 Iterations: Out of Memory Exception. Ln.: var writeableBitmap = new WriteableBitmap(rectangle, rectangle.RenderTransform);

仅通过注释掉"Fill = solidColorBrush"行,CreateImage()方法被调用了100次而没有任何问题-第100次迭代后,内存使用量约为"16 064 512字节".

Only by commenting out the line "Fill = solidColorBrush", the CreateImage() method was called 100 times without any problems - after the 100th iteration, memory usage was about "16 064 512 Bytes".

所以看来问题出在刷子上! 当用于填充UI元素时,此UI元素后来在可写位图上呈现,则该位图永远不会被垃圾回收.

So it seems the problem is the brush!! When used to fill an UI element, and later this UI elemnt is renderes on a writeable bitmap, the bitmap never gets garbage collected.

当然,我认为这毫无意义. 画笔超出范围,因此也应该将其收集为垃圾! (在使用画笔后将其设置为null不会更改任何内容)

Of course this makes no sense in my opinion. The brush runns out of scope so it simply should be garbage collected too! (Setting the brush to null after it was used did not change anything)

我的许多UI元素都使用笔刷填充,因此我不能简单地删除笔刷的使用. 您如何看待这个问题?

Many of my UI elements use a brush for filling, so i cannot simply remove the usage of brushes. What do you think about this issue?

推荐答案

问题是矩形.RenderTransform是对象的实例,如果将writableBitmap设置为null,则该矩形仍然有效.内存...所以解决方案是按如下方式编辑代码:

The Problem is that rectangle.RenderTransform is an instance of an object and if you set writableBitmap to null the rectangle.RenderTransform Object is still alive and holds the rectangle in the memory... so the solution is to edit the code as follows:

private void CreateImage()
{
   var rectangle = CreateRectangle();
   var writeableBitmap = new WriteableBitmap(rectangle, rectangle.RenderTransform);

   rectangle.RenderTransform = null; //and your memory would be happy ;)
   rectangle = null;
   writeableBitmap = null;
   GC.Collect();
}

查看内存屏幕截图...

see the memory screenshots...

之前:

之后:

这篇关于WriteableBitmap内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆