图片加载存储器泄漏C#
-
19-09-2019 - |
题
我有一个内存渗漏的问题,在我的应用其载荷大量的图像。我相当新,并认为我的日子存储器泄漏问题已过去。我不能找出问题的-也许我使用一些不受管理的模块,我不处理是否正确?
为了说明我的问题我已经简化的核心是什么原因导致的问题和移动这个清理项目。注意,这是所有愚蠢的代码不能反映原来应用它来自何处。在测试的应用程序,我有2个按钮,两个触发事件。
按钮1-创建:设定对象的属性.这将加载图像和让他们活着通过设定对象的属性:
var imgPath = @"C:\some_fixed_path\img.jpg";
DataContext = new SillyImageLoader(imgPath);
按钮2-清理:我的理解是,如果我让你走的参考持SillyImageLoader这再次举行的图像,那么这将被删除。我还明确地触发的垃圾收集只是看到立即的存储量的下降之后的参考。
DataContext = null;
System.GC.Collect();
在测试我的装载974KB jpeg图像。保持30位图表示的,这提升的存储器的使用我的应用程序从~18MB到-562MB."确定"。但当我打了清除的记忆只下降到-292MB.如果我重复创造+清理我的左边的另一个~250MB存储器。所以很明显的东西是仍然举行的人。
这里是SillyImageLoader码:
namespace MemoryLeakTest
{
using System;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
public class SillyImageLoader
{
private BitmapSource[] _images;
public SillyImageLoader(string path)
{
DummyLoad(path);
}
private void DummyLoad(string path)
{
const int numberOfCopies = 30;
_images = new BitmapSource[numberOfCopies];
for (int i = 0; i < numberOfCopies; i++)
{
_images[i] = LoadImage(path);
}
}
private static BitmapSource LoadImage(string path)
{
using (var bmp = new Bitmap(path))
{
return Imaging.CreateBitmapSourceFromHBitmap(
bmp.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
}
}
}
任何想法?该问题似乎是与。.只持有的位没有记忆丢失。我使用的。能够设置这个来源的财产的图像。我应该这样做有什么不同?如果是这样的-我还是想知道答案存储器泄漏。
谢谢。
解决方案
当你打电话
bmp.GetHbitmap()
一个复制的位是创建。你会需要保持一个参照指针,对象,并呼叫
DeleteObject(...)
上。
从 在这里,:
发言
你负责呼叫的 GDI然后您修改了组方法的免费的 存储器使用的GDI位的对象。
你可能能够保存自己的头疼(和开销)的复印位图通过使用 BitmapImage 而不是。.这可以让你来负荷,并创建一个步骤。
其他提示
您需要调用()从GetHBitmap返回的DeleteObject
指针的GDI IntPtr
方法。从该方法返回的IntPtr
是一个指向对象在内存中的副本。这必须使用下面的代码被手动释放:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
private static BitmapSource LoadImage(string path)
{
BitmapSource source;
using (var bmp = new Bitmap(path))
{
IntPtr hbmp = bmp.GetHbitmap();
source = Imaging.CreateBitmapSourceFromHBitmap(
hbmp,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hbmp);
}
return source;
}
看来,当调用GetHBitmap()你是负责释放对象
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
private void DoGetHbitmap()
{
Bitmap bm = new Bitmap("Image.jpg");
IntPtr hBitmap = bm.GetHbitmap();
DeleteObject(hBitmap);
}
我猜的的BitmapSource不承担此释放对象的责任。