C# 网络摄像头代码内存泄漏

C# 网络摄像头代码内存泄漏,c#,memory-leaks,webcam,video-capture,aforge,C#,Memory Leaks,Webcam,Video Capture,Aforge,好的,我一直在尝试通过网络摄像头的视频源做一些特定的事情。我有一个Lumenera Infinity 2显微镜,我正试图从中提取供体,希望能够在供体进入时修改供体。因为我找不到一种使用视频源播放器的方法,所以我决定将每一帧(相机最大15fps)作为位图,以便在那里进行修改 问题是:我有一个巨大的内存泄漏。当我使用videoSourcePlayer运行视频时,它的使用量大约为30兆。当我将帧作为位图运行时,它会在几秒钟内中断1G的内存 我错过了什么,在这里?我认为自动垃圾收集会在旧框架无法访问时将

好的,我一直在尝试通过网络摄像头的视频源做一些特定的事情。我有一个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。我已经编辑了我的答案,所以它应该修复交叉线程错误。