ImageSource / CreateBitmapSourceFromHBitmap中的内存泄漏(使用AForge捕获网络摄像头时)

时间:2015-03-09 22:08:03

标签: .net wpf memory-leaks aforge imagesource

我正在尝试将从网络摄像头捕获的内容输出到WPF窗口中的Image control。我正在使用AForge.NET库。

不幸的是,在成功捕获几分钟后,我得到OutOfMemoryException。同样,一旦我开始捕获,我就可以看到我的内存使用率在任务管理器中不断上升,直到异常时刻(尽管有几次内存使用率不断上升,然后急剧回落到其原始状态,然后再次上升到异常点。)

这是我NewFrame event VideoCaptureDevice class处理程序的代码(其Bitmap实例转换为ImageSource的代码主要基于{{3} } an answer):

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

private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
    try
    {
        using (var streamBitmap = (Bitmap)eventArgs.Frame.Clone()) {
            BitmapSource bitmapSourceVideo;

            var hBitmap = streamBitmap.GetHbitmap();
            try
            {
                bitmapSourceVideo = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    hBitmap,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
            }
            finally
            {
                DeleteObject(hBitmap);
            }
            bitmapSourceVideo.Freeze();

            Dispatcher.BeginInvoke(new ThreadStart(delegate
                                                       {
                                                           videoControl.Source = bitmapSourceVideo;
                                                       }));
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

如果你想知道,似乎需要调用eventArgs.Frame.Clone()。可以找到解释Sascha Hennig,可能还有here

在尝试隔离问题的根源时,我已经注释掉了这段代码的各个部分,直到我到达这个状态:

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

private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
    try
    {
        using (var streamBitmap = (Bitmap)eventArgs.Frame.Clone()) {
            BitmapSource bitmapSourceVideo;

            var hBitmap = streamBitmap.GetHbitmap();
            try
            {/*
                bitmapSourceVideo = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    hBitmap,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
            */}
            finally
            {
                DeleteObject(hBitmap);
            }
            /*
            bitmapSourceVideo.Freeze();

            Dispatcher.BeginInvoke(new ThreadStart(delegate
                                                       {
                                                           videoControl.Source = bitmapSourceVideo;
                                                       }));*/
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

(显然,这并没有在窗口中绘制任何内容,但现在已经不在了。)此版本的方法没有内存泄漏。通过调用here删除语句周围的注释符号会导致内存泄漏。 我在这里缺少什么?

关于看似相似的问题有各种各样的资源,但没有一个能帮助我找到解决方案:

1 个答案:

答案 0 :(得分:0)

我的直觉告诉我,这与位于委托中的bitmapSourceVideo有关,因此创建了一个闭包而没有被清理。

修改

尝试

        Dispatcher.BeginInvoke(new ThreadStart(delegate
        {
            videoControl.Source = bitmapSourceVideo;
            bitmapSourceVideo = null;
        }));