gpt4 book ai didi

c# - WriteableBitmap 内存泄漏?

转载 作者:IT王子 更新时间:2023-10-29 04:39:37 31 4
gpt4 key购买 nike

我正在使用下面的代码创建一个基于 UI 元素的动态磁贴。它在 WriteableBitmap 上呈现 uiElement,保存位图 + 返回文件名。此方法在 Windows Phone 后台任务代理中运行,我遇到了内存限制。

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

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

我也做了一些测试运行——在第一次运行这个方法之前:

Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
7.249.920 Bytes

没关系,因为附加了调试器,它使用大约 2 MB 内存。

再运行此方法(在调试器中重新设置为运行方法):

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

所以这个方法使用的内存增加了。

但是为什么?在我看来,没有任何引用可以阻止对象被收集。

2013 年 5 月 4 日更新

你好,

谢谢大家的回答!按照建议,我减少了代码 + 最终能够在几行代码中重现该问题。

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

启动应用后:ApplicationCurrentMemoryUsage: "11 681 792 Bytes"

1 次迭代 - ApplicationCurrentMemoryUsage:“28 090 368 字节”

5 次迭代 - ApplicationCurrentMemoryUsage:“77 111 296 字节”

20 次迭代 - ApplicationCurrentMemoryUsage:“260 378 624 字节”

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

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

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

当然这在我看来毫无意义。刷子超出范围,所以它也应该被垃圾收集!(使用后将画笔设置为null并没有改变任何东西)

我的许多 UI 元素都使用画笔进行填充,因此我不能简单地删除画笔的使用。你怎么看待这个问题?

最佳答案

问题是 rectangle.RenderTransform 是一个对象的实例,如果将 writableBitmap 设置为 null,则 rectangle.RenderTransform 对象仍然存在并将矩形保存在内存中......所以解决方案是将代码编辑为如下:

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

查看内存截图...

之前:

memory without setting rectangle.RenderTransform to null

之后:

memory with setting rectangle.RenderTransform to null

关于c# - WriteableBitmap 内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14710838/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com