从相机读取帧时RAM使用量增加

时间:2016-08-09 21:10:54

标签: vb.net memory-leaks camera aforge

我正在使用AForge库进行一些测试。我正在尝试读取来自我的usb相机(帧)的数据。它工作得很好,但唯一的问题是RAM。它泄漏了。似乎一帧占用了大约30 KB但是使用的内存不断增加。

这是我的代码:

Imports AForge
Imports AForge.Controls
Imports AForge.Video
Imports AForge.Video.DirectShow
Imports System.Threading
Imports System.IO
Imports System.Collections.Concurrent
Imports System.ComponentModel

Public Class Form1
    Dim sources As New FilterInfoCollection(FilterCategory.VideoInputDevice)
    Dim WithEvents device As VideoCaptureDevice
    Dim count As Long, bit As Bitmap
    Dim read As New Thread(AddressOf read_que)
    Dim pic_que As New ConcurrentQueue(Of Bitmap)


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For Each cam As FilterInfo In sources
            ComboBox1.Items.Add(cam.Name)
        Next
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        device = New VideoCaptureDevice(sources(ComboBox1.SelectedIndex).MonikerString)
        AddHandler device.NewFrame, new Video.NewFrameEventHandler(AddressOf frame)

        device.WaitForStop()
        device.Start()
    End Sub

    Sub frame(obj As Object, args As NewFrameEventArgs)
        If bit IsNot Nothing Then
            bit.Dispose()
            bit = Nothing
        End If
        bit = New Bitmap(args.Frame)

        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image.Dispose()))
        End If

        PictureBox1.Image =bit ' or ... = Imaging.Image.Clone(args.Frame)

    End Sub
End Class

我甚至尝试将所有帧放在并发队列中,然后在一个单独的线程中读取它(我发布了似乎占用内存最少的简化版本)。 但是还有另一个问题(这不是那么重要):当我启动应用程序时,图片框是空白的,使用的ram是16 MB(常量 - 所以它不起作用)。

只有当我进入任务管理器并按下结束进程(没有实际关闭它)时,它才会开始显示帧。我认为它与GUI有关(当我按下结束进程时,它可能会触发一个启动帧读取类的事件?)。 enter image description here

只是在随机时间它似乎从第一次开始工作(它确实可能是相机的问题,因为它老了并且仅适用于XP,所以我不得不使用.NET Framework 4。)

问题出在哪里(优先考虑的是公羊漏报)?

2 个答案:

答案 0 :(得分:1)

尝试使用:

Sub frame(obj As Object, args As NewFrameEventArgs)
    If Me.InvokeRequired Then
        Me.BeginInvoke(Sub() frame(obj, args))
    Else
        Dim oldImage = PictureBox1.Image

        Dim bitmap = New Bitmap(args.Frame)
        args.Frame.Dispose() 'Not sure if it has a Dispose
        PictureBox1.Image = bitmap

        If oldImage IsNot Nothing Then oldImage.Dispose()

    End If
End Sub

答案 1 :(得分:0)

解决了它。感谢您的所有帮助,但我知道我的代码正在运行(我在委托之前使用绘图框,因此它是线程安全的 - 我提供的代码是"快速和脏")。问题是...... VM。我正在测试VM上的代码。它适用于普通PC。

代码现在看起来像这样:

Imports AForge
Imports AForge.Controls
Imports AForge.Video
Imports AForge.Video.DirectShow
Imports System.Threading
Imports System.IO
Imports System.Collections.Concurrent
Imports System.ComponentModel

Public Class Form1
    Dim sources As New FilterInfoCollection(FilterCategory.VideoInputDevice)
    Dim device As VideoCaptureDevice
    Delegate Sub lp(ByRef pic As Bitmap)
    Delegate Sub lpp(nr As Integer, nr2 As Integer)
    Delegate Sub slp()
    Dim count As Long, bit As Bitmap
    Dim read As New Thread(AddressOf read_que)
    Dim pic_que As New ConcurrentQueue(Of Bitmap)


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For Each cam As FilterInfo In sources
            ComboBox1.Items.Add(cam.Name)
        Next
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        device = New VideoCaptureDevice(sources(ComboBox1.SelectedIndex).MonikerString)
        AddHandler device.NewFrame, new Video.NewFrameEventHandler(AddressOf frame)

        'device.WaitForStop()
        device.Start()

        'read.IsBackground = True
        'read.Start()
    End Sub

    Sub frame(obj As Object, args As NewFrameEventArgs)
        'If bit IsNot Nothing Then
        '    bit.Dispose()
        '    bit = Nothing
        'End If
        'bit = New Bitmap(args.Frame)

        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image.Dispose()))
        End If

        PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image = Imaging.Image.Clone(args.Frame))) 'Imaging.Image.Clone(args.Frame) ' or ...=bit
    End Sub
End Class