I'm making some tests with AForge library. I'm trying to read data coming from my usb camera(frames). It works very nice but the only problem is the RAM. It leaks. It seems taht a frame takes ~30 KB but the used memory keeps increasing.
Here's my code:
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
I tried even to put all the frames in a concurrent queue and then in a separate thread to read it(I posted the simplified version that seems to take the least ram memory).
But there's another problem (this is not that important): when I start the app the picturebox is blanck and the used ram is 16 MB (constant-so it doesn't work).
Only when I enter task manager and I press End Process(without actually closing it) it starts showing the frames. I thing it's GUI related(when I press the End Process maybe it fires an event that starts the frame-reading class?).
Only at random times it seems to work from the first time(it's true that it might be the camera's problem because it old and works only on XP so I had to use .NET Framework 4).
Where is the problem(the priority is the ram leakeage)?
Try using this:
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
Solved it. Thanks for all your help but I knew that my code was working(I used before a delegate to draw on picture box so it was thread-safe-the code I provided was "quick and dirty"). The problem was...the VM. I was testing the code on a VM. It works on a normal PC.
The code looks now like this:
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
Related
I would like get a little help from you. I am working on a diagram creator which can be called more than once. The diagram every time is different than the earlier version but I would like to use the same filename. The problem is that when I click on the button the program is showing the diagram form with the diagram in the picturebox but if the form is closed and I am clicking on the button again I have an error ("A generic error occurred in GDI+"). I think the mf.dispose() does not close the file and it opened. What do you think what is the problem, how can I solve it?
Main Form:
Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Diagram.create_diagram()
Diagram_FORM.PictureBox1.Image = New Metafile("c:\temp\test.wmf")
Diagram_FORM.Show()
End Sub
Diagram Class:
Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Class Diagram
Public Sub create_diagram()
Dim diagram_width As Integer = 600
Dim diagram_Height As Integer = 600
Dim filename As String = "c:\temp\test.wmf"
Dim gr As Graphics
gr = Graphics.FromImage(New Bitmap(diagram_width, diagram_Height))
' Make a Graphics object so we can use its hDC as a reference.
Dim hdc As IntPtr = gr.GetHdc
' Make the Metafile, using the reference hDC.
Dim bounds As New RectangleF(0, 0, Diagram_WidthSize, Diagram_HeightSize)
Dim mf As New Metafile(filename, hdc, bounds, MetafileFrameUnit.Pixel)
gr.ReleaseHdc(hdc)
' Make a Graphics object and draw.
gr = Graphics.FromImage(mf)
gr.PageUnit = GraphicsUnit.Pixel
gr.Clear(Color.White)
draw_diagram_background(gr)
draw_diagram_curve(gr)
gr.Dispose()
mf.Dispose()
End Sub
Private Sub draw_diagram_background(Byval gr as Graphics)
'some code
End Sub
Private Sub draw_diagram_curve(Byval gr as Graphics)
'some code
End Sub
End Class
You need to dispose Diagram_FORM.PictureBox1.Image when you close Form Diagram_FORM, otherwise exception will occur when you init Metafile with same filename c:\temp\test.wmf next time in method create_diagram() of class Diagram:
Dim mf As New Metafile(filename, hdc, bounds, MetafileFrameUnit.Pixel)
You can add the following code in your Diagram_FORM Form to dispose it's PictureBox1.Image when you close it.
Protected Overrides Sub OnFormClosed(e As FormClosedEventArgs)
If PictureBox1.Image IsNot Nothing Then
PictureBox1.Image.Dispose()
End If
MyBase.OnFormClosed(e)
End Sub
Imports System.Messaging
Imports System.Collections
Imports MSMQ
Imports System.IO
Imports System
Imports System.Messaging.MessageQueue
Imports System.Runtime.InteropServices
Public Class PauseOutMessages
'Declare everything to be in the scope of all methods.
Dim mgmt As New MSMQManagement
Dim outqmgmt As MSMQOutgoingQueueManagement
Dim q As New MSMQApplication
Dim outgoingQueues As New ArrayList
Dim myQueue As New MessageQueue("FormatName:DIRECT=OS:myMachine\Private$\myQueue", QueueAccessMode.ReceiveAndAdmin)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each queue In q.ActiveQueues
If queue.IndexOf("DIRECT=") >= 0 Then
outgoingQueues.Add(queue)
End If
Next
End Sub
Private Sub Pause_Click(sender As Object, e As EventArgs) Handles Pause.Click
For Each queuePath In outgoingQueues
mgmt.Init(FormatName:=queuePath)
outqmgmt = mgmt.Pause()
Next
End Sub
Private Sub Restart_Click(sender As Object, e As EventArgs) Handles Restart.Click
For Each queuePath In outgoingQueues
mgmt.Init(FormatName:=queuePath)
outqmgmt = mgmt.Resume()
Next
End Sub
Private Sub Send_Click(sender As Object, e As EventArgs) Handles Send.Click
myQueue.Send("Test")
For Each queue In q.ActiveQueues
If queue.IndexOf("DIRECT=") >= 0 Then
outgoingQueues.Add(queue)
End If
Next
End Sub
End Class
Here is the code I am using, by sending the test message to a non-existing path it gets stuck in the outgoing queue where I want to be able to call MSMQOutgoingQueueManagement.Pause or .Resume to be able to start and stop all outgoing queues.
However I keep getting an error on either mgmt.Pause() or mgmt.Resume() saying Access is denied. I can't seem to find a way to get on to the properties of outgoing queues to be able to adjust security settings. Any help would be greatly appreciated!
SOLVED!
Turns out I just needed to start up visual studio as an administrator and then it worked.
lets go with the idea that i know nothing about nothing...
https://www.youtube.com/watch?v=37l6-O0T6EA
I was following this vids, all going well. but failing on "capturez.QueryFrame"
Imports Emgu.CV
Imports Emgu.CV.Util
Imports Emgu.CV.Structure
Public Class Form1
Dim capturez As Capture = New Capture
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim imagez As Image(Of Bgr, Byte) = capturez.Retrieve() 'Instead of QueryFrame, you may need to do RetrieveBgrFrame depending on the version of EmguCV you download.
PictureBox1.Image = imagez.ToBitmap()
End Sub
End Class
There is no Retrieve() method in vb.
Try to replace capturez.Retrieve() with capturez.QueryFrame() or Capturez.RetrieveBgrFrame().
If you already changed that but you get failing on capturez.QueryFrame, it means you are missing some dll files in x86 (bin/debug).
I'm trying to use the VlcDotNet library to embed a small media player into a VB.Net forms-based project.
Mainly I'm following the solution that I found here:
Display video with VlcDotNet library
except that I've had to translate from C# to VB.
Having followed the instructions to the letter, there are two lines of the code which simply aren't recognised and won't compile. Certain methods of the Vlc.DotNet.Core code simply aren't accepted as valid.
Having used NuGet to get 4 Vlc.DotNet packages (.Core, .Core.Interops, .Forms and .Wpf), my complete code (excluding the very basic design of one button and one panel) is below. The compiler won't compile it, because it says there are 2 errors.
Firstly, "Type Vlc.DotNet.Core.Medias.MediaBase is not defined" (for the 'Dim newMedia as...' line)
Secondly, "'Media' is not a member of 'Vlc.DotNet.Forms.Control" (for the '.Media = newMedia' line)
Almost all the methods of the VlcControl are present, but I can't see why certain elements, such as the Media method, are simply not there?
Any suggestions would be extremely welcome.
Thanks
Imports Vlc.DotNet.Core
Imports Vlc.DotNet.Core.Interops
Imports Vlc.DotNet.Forms
Imports Vlc.DotNet.Wpf
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim player As New Vlc.DotNet.Forms.VlcControl
Panel1.Controls.Add(player)
With player
.BackColor = Color.Blue
.ImeMode = Windows.Forms.ImeMode.NoControl
.Location = New System.Drawing.Point(0, 0)
.Name = "test"
.Rate = 0.0F
.Size = Panel1.Size
Dim newMedia As Vlc.DotNet.Core.Medias.MediaBase = New Vlc.DotNet.Core.Medias.PathMedia("E:\TempTest.mov")
.Media = newMedia
.Play()
End With
End Sub
End Class
I had try to convert out from C# and below are the new library files using method:
Public myvlc As New VlcControl
myvlc.Dock = DockStyle.None
myvlc.Size = New Size(myscreen.Bounds.Width, myscreen.Bounds.Height)
myvlc.Location = New Point(0, 0)
Me.Controls.Add(myvlc)
AddHandler myvlc.VlcLibDirectoryNeeded, AddressOf LibNeeded
Private Sub LibNeeded(ByVal Sender As Object, ByVal e As VlcLibDirectoryNeededEventArgs)
e.VlcLibDirectory = New IO.DirectoryInfo("C:\lib\x86\")
End Sub
Please download the Video Codec lib from the same website where you get the vlc.dotnet.
I had the following code written using EWS to subscribe to Pull notifications and read new emails. It was working all fine. All of a sudden it does not read the new emails. Any ideas what could the cause be? And how to resolve it?
Imports Microsoft.Exchange.WebServices.Data
Imports System.Threading
Public Class FormTest
Dim subscription As PullSubscription
Dim service As ExchangeService
Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click
service = New ExchangeService
service.Credentials = New WebCredentials("myusername", "mypassword", "mydomain")
service.Url = New Uri("https://webmail.mydomain.com/EWS/exchange.asmx")
subscription = service.SubscribeToPullNotifications(New FolderId() {WellKnownFolderName.Inbox}, 1440, Nothing, EventType.NewMail)
End Sub
Private Sub ButtonPoll_Click(sender As Object, e As EventArgs) Handles ButtonPoll.Click
PollEmails()
End Sub
Private Sub PollEmails()
Dim events As GetEventsResults = subscription.GetEvents()
For Each itemEvent As ItemEvent In events.ItemEvents
Dim message As EmailMessage = EmailMessage.Bind(service, itemEvent.ItemId)
message.Load()
' Do something with 'message'
Next
End Sub
End Class
Basically when I press ButtonPoll events does not contain any new evenets, even though there has been new emails since the ButtonStart was pressed.
Heyo!! I am doing something very similar. Looks like you have posted this question a month and a half ago so you may have solved it by now, but I wanted to put my initial experiences up here for anyone else that may be looking. The way I am posting below is a way to get notifications without having to push a poll button. This may help! I stripped all my fancy stuff out, as it is always important to learn, but this initial part of it was the most obnoxious part to figure out.
Imports System.Net
Imports System.Net.Security
Imports Microsoft.Exchange.WebServices.Data
Imports System.Security.Cryptography.X509Certificates
Public Class MainForm
Private Sub ExecuteButton_Click(sender As System.Object, e As System.EventArgs) Handles ExecuteButton.Click
Console.Clear()
Dim exch As ExchangeService = New ExchangeService(ExchangeVersion.Exchange2010_SP2)
exch.Url = New Uri("https://" + ExchangeURLTB.Text + "/EWS/Exchange.asmx")
exch.UseDefaultCredentials = False
exch.Credentials = New System.Net.NetworkCredential(UsernameTB.Text, PasswordTB.Text, DomainTB.Text)
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateCertificate)
Dim subscribeStreaming As StreamingSubscription = exch.SubscribeToStreamingNotifications(New FolderId() {WellKnownFolderName.Inbox}, EventType.NewMail, EventType.Created, EventType.Deleted)
Dim subscribeStreamingConnection = New StreamingSubscriptionConnection(exch, 30)
subscribeStreamingConnection.AddSubscription(subscribeStreaming)
AddHandler subscribeStreamingConnection.OnNotificationEvent, AddressOf OnNotificationEvent
AddHandler subscribeStreamingConnection.OnSubscriptionError, AddressOf OnSubscriptionError
AddHandler subscribeStreamingConnection.OnDisconnect, AddressOf OnDisconnect
subscribeStreamingConnection.Open()
Console.Write("Steaming subscription open")
End Sub
Private Sub OnNotificationEvent(sender As Object, args As NotificationEventArgs)
Dim subscription As StreamingSubscription = args.Subscription
For Each notification As NotificationEvent In args.Events
Select Case notification.EventType
Case EventType.NewMail
Console.WriteLine(vbNewLine)
Console.WriteLine("-------------Mail created:-------------")
End Select
Next
End Sub
Private Sub OnSubscriptionError(sender As Object, args As SubscriptionErrorEventArgs)
End Sub
Private Sub OnDisconnect(sender As Object, args As SubscriptionErrorEventArgs)
End Sub
Private Function ValidateCertificate(ByVal sender As Object, ByVal certificate As X509Certificate, ByVal chain As X509Chain, ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
'Return True to force the certificate to be accepted.
Return True
End Function
End Class