我正在使用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有关(当我按下结束进程时,它可能会触发一个启动帧读取类的事件?)。
只是在随机时间它似乎从第一次开始工作(它确实可能是相机的问题,因为它老了并且仅适用于XP,所以我不得不使用.NET Framework 4。)
问题出在哪里(优先考虑的是公羊漏报)?
答案 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