用C#图片加载内存泄漏 [英] Image loading memory leak with C#

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

问题描述

我在我的应用程序的内存泄漏问题,它加载了大量的图像。我是相当新的C#和思想的内存泄漏问题我的日子过了。我想不通的问题 - 也许我使用一些非托管的模块,我没有正确处理?

I have a memory leak issue in my application which loads a large amount of images. I'm rather new to C#, and thought my days of memory leak issues were past. I can't figure out the problem - maybe I'm using some unmanaged modules which I'm not handle correctly?

要说明我的问题,我已经简化了是什么原因导致问题的核心,并提出这一个干净的项目。请注意,这是所有愚蠢code并不反映它来自原始应用程序。在测试应用程序,我有2个按钮,触发两个事件。

To illustrate my problem I've simplified the core of what causes the problem and moved this to a clean project. Note that this is all silly code which doesn't reflect the original application it came from. In the test application I have 2 buttons, triggering two events.

按钮1 - 创建:设置对象到DataContext。这将加载图像,并让他们活着的对象设置到DataContext:

Button 1 - Create: Setting an object to the datacontext. This will load the images and keep them alive by setting the object to the DataContext:

var imgPath = @"C:\some_fixed_path\img.jpg";
DataContext = new SillyImageLoader(imgPath);

按钮2 - 清理:我的理解是,如果我放手的参考保留这又保持图像的SillyImageLoader的,那么这将被删除。我也明确地引发垃圾收集只是立即看到丢弃的参考之后的内存量。

Button 2 - CleanUp: My understanding is that if I let go of the reference holding the SillyImageLoader which again holds the images, then this will be deleted. I also explicitly trigger garbage collection just to see immediately the amount of memory after dropping the reference.

DataContext = null; 
System.GC.Collect();

在测试我加载一个974KB的JPEG图像。持这种30位重新presentations提高我的应用程序,从〜18MB到〜562MB的内存使用情况。好。但是,当我打的清理记忆力下降只是〜292MB。如果我重复创建+清理我留下了另一个〜250MB的内存。所以很明显的东西还是有人持有。

When testing I'm loading a 974KB jpeg image. Holding 30 bitmap representations of this boosts the memory usage of my application from ~18MB to ~562MB. Ok. But when I hit cleanup the memory drops only to ~292MB. If I repeat Create+CleanUp I'm left with another ~250MB memory. So obviously something is still held by someone.

下面是SillyImageLoader- code:

Here is the SillyImageLoader-code:

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

任何想法?这个问题似乎是与的BitmapSource。只持有该位图是没有内存泄漏。我使用的BitmapSource才能够将其设置为图像的来源属性。我应该这样做不同?如果是这样的 - 我还是想知道答案的内存泄漏。

Any ideas? The problem seems to be with the BitmapSource. Holding only the Bitmap there is no memory leak. I am using BitmapSource to be able to set this to the Source property of an Image. Should I do this differently? If so - I'd still like to know the answer the memory leak.

感谢。

推荐答案

当你调用

bmp.GetHbitmap()

位图的一个副本被创建。你需要保持一个参考指针,该对象,并调用

a copy of the bitmap is created. You'll need to keep a reference to the pointer to that object and call

DeleteObject(...)

就可以了。

这里

备注

您是负责调用   GDI DeleteObject方法以释放   使用的内存GDI位图对象。

You are responsible for calling the GDI DeleteObject method to free the memory used by the GDI bitmap object.


您可能能够保存自己复制位图的头痛(和开销)使用<一个href="http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.aspx">BitmapImage中的BitmapSource代替。这使您可以加载并创建一个步骤。

You may be able to save yourself the headache (and overhead) of copying the bitmap by using BitmapImage instead of BitmapSource. This allows you to load and create in one step.

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

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