我正在尝试将从网络摄像头捕获的内容输出到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删除语句周围的注释符号会导致内存泄漏。 我在这里缺少什么?
关于看似相似的问题有各种各样的资源,但没有一个能帮助我找到解决方案:
CreateBitmapSourceFromHBitmap
假设我从一个URI加载,我可以将其加载到一个流中。Freeze
解决方案不适用,因为泄漏不会根据我是否评论或取消注释我对Freeze
的调用而改变。 this blogpost进一步证实了这一点。DeleteObject
,就需要调用GetHbitmap
不再需要。 this blogpost也提出了这一点。我已经在代码中这样做了。Bitmap
,但由于Bitmap
阻止,我已经处理了我自己创建的任何using
个实例答案 0 :(得分:0)
我的直觉告诉我,这与位于委托中的bitmapSourceVideo有关,因此创建了一个闭包而没有被清理。
修改强>
尝试
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
videoControl.Source = bitmapSourceVideo;
bitmapSourceVideo = null;
}));