为什么我在捕捉图像时会耗尽内存?

时间:2014-05-15 13:20:11

标签: wpf memory

大约10秒钟后,我得到一个例外,即内存不足。

enter image description here

此代码中出现错误,其中捕获图像并在UI上显示:

private void onFrameEvent(object sender, EventArgs e)
{
    uEye.Camera Camera = sender as uEye.Camera;

    Int32 s32MemID;
    Camera.Memory.GetActive(out s32MemID);


    // Read Camera bitmap
    Bitmap bitmap;
    Camera.Memory.ToBitmap(s32MemID, out bitmap);


    Dispatcher.Invoke(new Action(() =>
    {
        // Convert bitmap to WPF-Image
        var bmp = new Bitmap(bitmap);
        var hBitmap = bmp.GetHbitmap();

        System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            hBitmap, IntPtr.Zero, Int32Rect.Empty,
            BitmapSizeOptions.FromEmptyOptions());

        image1.Source = wpfBitmap;
        image1.Stretch = System.Windows.Media.Stretch.UniformToFill;

        DeleteObject(hBitmap);
    }));
}

如何避免如此庞大的内存访问?

1 个答案:

答案 0 :(得分:0)

几年前,我对WPF和图像存在内存问题。它似乎是WPF中的一个错误。

以下代码似乎已经处理过了。差异似乎是你没有调用source.Freeze(),bitmap.Dispose()和GC.Collect()。我假设DeleteObject与我的相同。

public static class BitmapEx
{
    /// <summary>
    /// Converts a Bitmap object to WPF 'ImageSource' object and 
    /// garbage collects to Bitmap object.
    /// </summary>
    public static ImageSource ToImageSource(this Bitmap bitmap)
    {
        IntPtr hBitmap = bitmap.GetHbitmap();
        try
        {
            ImageSource source = Imaging.CreateBitmapSourceFromHBitmap(
                    hBitmap, 
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions()
            );

            source.Freeze();
            return source;
        }
        finally
        {
            if (!Win32Image.DeleteObject(hBitmap))
                Debug.WriteLine("BitmapEx.ToImageSource() - Unable to Delete hBitmap");   

            bitmap.Dispose();
            bitmap = null;
            GC.Collect();
        }
    }
}

[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static class Win32Image
{
    public static bool DeleteObject(IntPtr handle)
    {
        return NativeMethods.DeleteObject(handle);
    }

    private static class NativeMethods
    {
        [DllImport("gdi32.dll", SetLastError = true)]
        public static extern bool DeleteObject(IntPtr hObject);
    }
}

在将大量图像(50+)加载到窗口时仍然遇到问题,事后看来这可能是由GC.Collect()调用引起的(我只是没有将图像加载到该窗口上)页)。如果遇到该问题,您可能会尝试限制调用GC.Collect()的次数。

[编辑]

调用GC.Collect()被认为是个坏主意(请参阅注释)。

尝试使用不带GC.Collect()的代码。如果它适合你,那么我将从这个答案中删除GC.Collect()行。