【问题标题】:Out of memory exception C# freezable.freeze内存不足异常 C# freezable.freeze
【发布时间】:2010-12-07 20:08:41
【问题描述】:

我正在尝试将一些图片复制到 RAM,但这会导致内存不足异常.. 我不知道为什么,但我认为这是“冻结()”的原因。但是如何“解冻”,这真的是问题吗?

        public void preLoadThread(Object o)
    {
        Overlay ov = (Overlay)o;
        ImageSource tempNext = BitmapConverter(ov.tempPreLoadPathNext);
        ImageSource tempPrev = BitmapConverter(ov.tempPreLoadPathPrev);
        tempNext.Freeze();
        tempPrev.Freeze();
        ov.Dispatcher.Invoke(
            DispatcherPriority.Normal,
            (Action)delegate()
            {
                ov.preLoadedNext = tempNext;
                ov.preLoadedPrev = tempPrev;
                ov.preLoadPathNext = ov.tempPreLoadPathNext;
                ov.preLoadPathPrev = ov.tempPreLoadPathPrev;
            }
        );
    }

    public BitmapSource BitmapConverter(String path)
    {
        System.Drawing.Bitmap b = null;
        using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
        {
            try
            {
                b = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(fs);
            }
            catch (Exception)
            {
                GC.Collect();
                GC.WaitForFullGCComplete();
            }
            fs.Close();
        }

        if ( b == null)
        {
            // Error
            return null;
        }

        BitmapSizeOptions options = BitmapSizeOptions.FromEmptyOptions();
        BitmapSource bs = null;
        try
        {
            bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
               b.GetHbitmap(),
               IntPtr.Zero,
               Int32Rect.Empty,
               options);
        }
        catch (Exception)
        {
            GC.Collect();
            GC.WaitForFullGCComplete();
        }
        return bs;
    }

【问题讨论】:

  • GC.Collect 在 catch 块中不是答案。
  • 我知道.. 这是尝试和错误,因为我不知道如何修复此泄漏
  • 您尝试处理的图像有多大?
  • 1378x2000.. 由于某些缩放功能,我无法缩小它们。

标签: c# visual-studio multithreading


【解决方案1】:

我真诚地怀疑内存异常是否来自 Freeze() 调用,因为这实际上并没有分配任何内存。

我很确定您有 GDI 泄漏...您必须在调用 CreateBitmapSourceFromHBitmap() 后在创建的位图上调用 DeleteObject...但是因为您将 GetHbitmap() 作为参数调用,所以您有没有要删除的句柄。

试试这个:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

...

IntPtr hObject = b.GetHbitmap();
bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
           hObject,
           IntPtr.Zero,
           Int32Rect.Empty,
           options);

DeleteObject(hObject);


Henk 是对的,您不应该强制进行 GC 收集……它并没有真正帮助您,因为无论如何您并没有真正释放任何要收集的东西(您释放的唯一东西必须通过 DeleteObject 清理()。

我们在谈论多少张 1378x2000 的图片?即使您修复了 GDI 泄漏,这些都是大图并且会很快耗尽内存。

Curtisk 是对的,你不能解冻,你必须克隆......但是当你这样做时你会分配内存。只是为了警告你。

我想在 64 位下运行不是一个选项...

【讨论】:

  • 什么是DeleteObject()?我错过了参考吗?
  • 这是对gdi32.dll DLL(Windows 的一部分)中的调用的声明。声明上方的属性告诉 .NET 在运行时导入该 DLL,并告诉它在代码中的何处查找 DeleteObject() 调用。请注意,您正在调用非托管代码,其中有许多含义。链接到更多信息:msdn.microsoft.com/en-us/library/…
【解决方案2】:

至于你的“解冻”问题,你不能在初始项目上,但你可以剥离一个解冻的克隆,details and example at MSDN

【讨论】:

    猜你喜欢
    • 2012-01-23
    • 2016-07-27
    • 2010-09-17
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    相关资源
    最近更新 更多