内存异常C#freezable.freeze

时间:2010-12-07 20:08:42

标签: c# visual-studio multithreading

我正在尝试将一些图片复制到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;
    }

2 个答案:

答案 0 :(得分: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位下运行不是一种选择......

答案 1 :(得分:0)

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