内存泄漏,但是在哪里? [英] Memory leak, but where?

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

问题描述

我不明白这里泄漏了什么

I can't understand what is leaking here

using GDI = System.Drawing;

public partial class MainWindow : Window
{
    [DllImport("gdi32.dll")]
    private static extern bool DeleteObject(IntPtr obj);

    public MainWindow()
    {
        InitializeComponent();

        var timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(50) };
        timer.Tick += (s, a) =>
        {
            using (var bitmap = new GDI.Bitmap(1000, 1000))
            {
                var hbitmap = bitmap.GetHbitmap();
                var image = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                image.Freeze();
                DeleteObject(hbitmap);
            }
        };
    timer.Start();
}

bitmap?处置. hbitmap?已删除. image?已冻结,它不是IDisposable.

bitmap? Disposed. hbitmap? Deleted. image? Frozen and it's not IDisposable.

事实是,此应用程序将崩溃(仅在运行约20秒后在我的PC上)

The fact is, this application will crash (on my PC after just ~20 seconds of running)

System.Drawing.dll中发生了'System.OutOfMemoryException'类型的未处理异常

An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll

其他信息:内存不足.

有什么想法吗?

推荐答案

据我所知,没有发生泄漏.问题是您正在快速分配大型C#对象,而垃圾收集器启动得太晚了?

As far I can tell, there are no leaks going on. The problem is that you're allocating big C# objects fast and garbage collector kicks in way too late?

以下是一些相关主题:

避免在进行大型,快速和频繁的内存分配时出现OutOfMemoryException C#

这是有用的线程:

即使在需要时也不会发生垃圾收集

如果您踢GC.Collect(第0..3代),则您的内存消耗将被固定:

If you kick GC.Collect(with generations 0..3), your memory consumption will be fixed:

    while (true)
    {
        Thread.Sleep(5);

        using (var bitmap = new GDI.Bitmap(1000, 1000))
        {
            var hbitmap = bitmap.GetHbitmap();
            var image = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            image.Freeze();


          DeleteObject(hbitmap);
        }

        Console.WriteLine("Current memory consumption" + GC.GetTotalMemory(false));
        GC.Collect(3);
    }

并输出:

Current memory consumption156572
Current memory consumption156572
Current memory consumption156572
Current memory consumption156572

真正的问题是,即使您释放了非托管分配,GC也不知道.您需要增加内存压力,并让GC知道:

The real problem is that GC does not know about your unmanaged allocations, even if you free them. You need to add memory pressure and let the GC know about it:

 var width = 1000;
                var height = 1000;

                using (var bitmap = new GDI.Bitmap(width, height))
                {
                    var hbitmap = bitmap.GetHbitmap();
                    var allocatedSize = width*height*4; // each pixel takes ~4 bytes?!
                    GC.AddMemoryPressure(allocatedSize);

                    var image = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty,
                        BitmapSizeOptions.FromEmptyOptions());

                    image.Freeze();


                    DeleteObject(hbitmap);
                    GC.RemoveMemoryPressure(allocatedSize);
                }

让GC知道底层的非托管内存有助于确保GC插入正确的位置.

Letting GC know about underlying unmanaged memory helps to make sure GC kicks in at right places.

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

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