C# 网络摄像头代码内存泄漏
好的,我一直在尝试通过网络摄像头的视频源做一些特定的事情。我有一个Lumenera Infinity 2显微镜,我正试图从中提取供体,希望能够在供体进入时修改供体。因为我找不到一种使用视频源播放器的方法,所以我决定将每一帧(相机最大15fps)作为位图,以便在那里进行修改 问题是:我有一个巨大的内存泄漏。当我使用videoSourcePlayer运行视频时,它的使用量大约为30兆。当我将帧作为位图运行时,它会在几秒钟内中断1G的内存 我错过了什么,在这里?我认为自动垃圾收集会在旧框架无法访问时将其清除。我应该尝试强制位图上的垃圾收集吗?或者完全是别的什么东西,而我却毫不犹豫地错过了C# 网络摄像头代码内存泄漏,c#,memory-leaks,webcam,video-capture,aforge,C#,Memory Leaks,Webcam,Video Capture,Aforge,好的,我一直在尝试通过网络摄像头的视频源做一些特定的事情。我有一个Lumenera Infinity 2显微镜,我正试图从中提取供体,希望能够在供体进入时修改供体。因为我找不到一种使用视频源播放器的方法,所以我决定将每一帧(相机最大15fps)作为位图,以便在那里进行修改 问题是:我有一个巨大的内存泄漏。当我使用videoSourcePlayer运行视频时,它的使用量大约为30兆。当我将帧作为位图运行时,它会在几秒钟内中断1G的内存 我错过了什么,在这里?我认为自动垃圾收集会在旧框架无法访问时将
FilterInfoCollection captureDevices;
VideoCaptureDevice cam;
Bitmap bitmap;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
captureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (captureDevices.Count == 0)
throw new ApplicationException();
CameraSelectComboBox.Items.Clear();
foreach (FilterInfo device in captureDevices)
{
CameraSelectComboBox.Items.Add(device.Name);
}
CameraSelectComboBox.SelectedIndex = 0;
CameraSelectComboBox.Enabled = true;
}
catch (ApplicationException)
{
CameraSelectComboBox.Enabled = false;
}
}
private void connectButton_Click(object sender, EventArgs e)
{
cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on
cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
videoSourcePlayer1.Visible = false;
cam.Start();
//videoPictureBox1.Visible = false;
//videoSourcePlayer1.VideoSource = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
//videoSourcePlayer1.Start();
}
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
bitmap = (Bitmap)eventArgs.Frame.Clone();
videoPictureBox1.Image = bitmap;
}
我认为这是一个需要改进的领域:
cam = new
VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
cam.NewFrame -= Handle_New_Frame; // you're pointing to the new instance of VCD, so this will have no effect.
cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
videoSourcePlayer1.Visible = false;
cam.Start();
每次按下“连接”按钮时,该代码块都在释放内存
你几乎需要在主要层面上参考VCD。因此,在Form1类级别定义一个成员变量:
private VideoCaptureDevice _cameraContext;
在connect事件处理程序中,执行以下操作:
if (_camerContext != null)
{
_cameraContext.NewFrame -= Handle_New_Frame;
}
_cameraContext = new VideoCaptureDevice(blah blah blah);
_cameraContext.NewFrame += Handle_New_Frame;
videoSourcePlayer1.Visible = false;
_cameraContext.Start();
顺便说一句,我假设您是.NET 3.5或更高版本,因此使用了新的委托分配语法。尝试以下方法:
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
if(bitmap != null)
bitmap.Dispose();
bitmap = new Bitmap(eventArgs.Frame);
if(videoPictureBox1.Image != null)
this.Invoke(new MethodInvoker(delegate() {videoPictureBox1.Image.Dispose();}));
videoPictureBox1.Image = bitmap;
}
它解决了我在使用RGE和PictureBoxes时遇到的一些内存泄漏问题,但就内存消耗而言,VideoSourcePlayer要好得多。
Bitmap
是IDisposable
只是一个快速猜测:可能是处理新帧事件?它正在克隆一个帧,调用这个事件的次数和速度是多少?我假设在每一帧,每秒最多15次(基于硬件)。我将检查并确保这里有类似的问题:注意:这只是我看到明显泄漏的一个代码区域。考虑到内存泄漏非常严重,您还应该看看位图是如何处理的。太棒了!非常感谢你提供的信息。是的,你的假设是正确的-我用的是4.5真棒!那应该会有帮助的!不过,我遇到了一个问题——在videoPictureBox1.Image.Dispose()上出现了一个跨线程错误。“跨线程操作无效:控件‘videoPictureBox1’是从创建它的线程以外的其他线程访问的。”您在处理此操作时是否偶然遇到此问题?啊,是的,您需要使用Invoke。我已经编辑了我的答案,所以它应该修复交叉线程错误。