【问题标题】:C# Get image source from project resources creates memory leakC# 从项目资源中获取图像源会导致内存泄漏
【发布时间】:2013-07-28 11:03:57
【问题描述】:

好的,在我的项目资源中,我有一些图片 (.png)。每当用户单击Button 时,一个新图像将显示在ImageBox 中。因为我所有的图像都存储在我的项目资源中,所以我必须通过代码获取Image.Source。我设法通过使用这样的Method 来做到这一点:

 public void ImageSource()
 {
     Bitmap someImage;
     BitmapSource someImageSource;

     someImage= new Bitmap(Properties.Resources.Image1);
     someImageSource = getBitmapSourceFromBitmap(someImage);
     ImageBox.Source = someImageSource;
 }

 public static BitmapSource getBitmapSourceFromBitmap(Bitmap bmp)
 {  
     BitmapSource returnSource = null;

     try
     {
         returnSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
     }
     catch { returnSource = null; }

     return returnSource;

 }

在我的应用程序中一切正常。没有错误,没有警告,每次我推送Button 时图像都会改变。在内存中进行了一些监控之后,我注意到每次调用getBitmapSourceFromBitmap 我的内存每次都会爆炸 100MB。 有谁知道为什么会这样? 对不起我的英语。

【问题讨论】:

    标签: c# memory-leaks resources bitmapsource


    【解决方案1】:

    您正在使用非托管资源从您的图像创建位图。 GC 不处理分配给非托管资源的内存。您需要处理在该方法中使用的内存。

    将图像转换为位图后,您需要释放所有非托管资源。

    我的内存每次爆炸 100MB

    一般来说,如果您的内存增加 100MB 并不意味着您有内存泄漏。在托管资源的情况下,只要觉得可行,GC 就会收集所有可收集的内存。

    您的问题:MSDN中所述

    你负责调用 GDI DeleteObject 方法来释放 GDI 位图对象使用的内存

    你需要像这样改变你的代码

    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);
    
    
    using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(1000, 1000)) {
        IntPtr hBitmap = bmp.GetHbitmap();
        try {
            var source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        }
        finally {
            DeleteObject(hBitmap)
        }
    }
    

    【讨论】:

    • 完美。十分感谢。经过一番搜索,我发现如果图像的格式不是 .png,Imaging.CreateBitmapSourceFromHBitmap 可能会导致内存问题。在将我的所有图像转换为非透明 .png 图像(每张图像约 9kB)后,一切都很顺利。而且您的解决方案很完美,所以我会检查它是否已回答,以便其他有同样问题的人有指导。再次感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-27
    相关资源
    最近更新 更多