VB MyParameters Class Appears to Stop - vb.net

I'm passing values to and from a Background worker. To do this I'm using the following class to store the variables:
Class MyParameters
Friend _QueryStr As String
Friend _Value_CreatedDate As Object
Friend _AccountID As Object
Friend _Last_Login As Object
Friend _Motto As Object
Friend _Bio As Object
Friend _pFavourite_Game As Object
Friend _pFacebookLink As Object
Friend _pInstagram As Object
Friend _pTwitterLink As Object
Friend _pTumblerLink As Object
Friend _pYoutubeLink As Object
Friend _lblpYoutubeLink As String
Friend _lblpTumblerLink As String
Friend _lblpTwitterLink As String
Friend _lblpInstagram As String
Friend _lblFacebookLink As String
Friend _lblpFavourite_Game As String
Friend _lblBio As String
Friend _lblMotto As String
Friend _lblLast_Login As String
Friend _AccessCode As String
Friend _TargetUGPoints As String
Friend _Stream As New MemoryStream()
Friend _Image As Byte()
Friend _DoB_Value As Object
Friend _DoB As Date
Friend _Years As Integer
Friend _Months As Integer
Friend _Cautions_Value As Integer
Friend _Cautions As Integer
Friend _Bitmap As New Bitmap(_Stream)
Friend _Con As New SqlConnection("Data Source =" & My.Settings.ServerIP & ";Initial Catalog=Atlas;Integrated Security=False;User=" & My.Settings.UserName & ";Password=leaders132;")
Friend _MyCMD As New SqlCommand(_QueryStr, _Con)
End Class
And I'm calling the background worker like this on a forms load event:
Private Sub cdb_ProfileViewer_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Loadinglbl.Visible = True
SpinningProgress1.Visible = True
MsgBox("Starting MyParamters")
Dim m As New MyParameters
MsgBox("My Parameters set to m")
bw.RunWorkerAsync(m)
End Sub
However, the application doesn't seem to reach the background worker. There's no freezing or errors, it simply does nothing. I remain in control of the form like the background worker is working, but I dont think it's even starting because it doesn't run any msgbox's. For example, I've included a Msgbox in my code to let me know which stage the code has reached. It works if I place it before Dim m as New Parameter, but not after.
My Background worker, note I've omitted my code as it's lenthy:
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Dim m As MyParameters = DirectCast(e.Argument, MyParameters) 'Convert the generic Object back into a MyParameters object
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
e.Result = m
'Do some time-consuming work on this thread
end sub
My WorkerCompleted Event, also without code:
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
Dim m As MyParameters = DirectCast(e.Result, MyParameters) 'Convert the generic Object back into a MyParameters object
MsgBox("Reached Worker Complete")
'Called when the BackgroundWorker is completed.
end sub
My BW Public Class Code:
Private bw As BackgroundWorker = New BackgroundWorker
Private Delegate Sub ButtonClick(ByVal sender As Object, ByVal e As EventArgs)
And the Public Sub responsible for the BW:
Public Sub New()
InitializeComponent()
bw.WorkerReportsProgress = False
bw.WorkerSupportsCancellation = False
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
End Sub
Is there anything that's jumping out at you? As I say, I feel it's something in my Class MyParamters.

The Load() event unfortunately swallows your exception. Move that code to the Constructor or the Shown() event and the problem becomes apparent:
Friend _Bitmap As New Bitmap(_Stream)
You can't create a Bitmap from an Empty Stream...
Minimum code to reproduce:
Public Class MyParameters
Friend _Stream As New MemoryStream()
Friend _Bitmap As New Bitmap(_Stream)
End Class
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim M As New MyParameters
End Sub

Related

how to safe call a control from another thread using Timers.Timer

I read various posts, and made a practice project, but it does not works.
The form have a button and a text box with a default text 'Updated 0 times'. On button click starts the timer and each time update the text with the number of times the text was updated.
The exception of cross thread calls is not thrown, but when calling the text box, its .Text = "", the text is updated but not the text box on the form. And InvokeRequired is always false.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Here the textBox.Text = "Updated 0 times."
Dim checking_text As String = Me.TextBox1.Text
TimerTest.StartTimer()
End Sub
Delegate Sub UpdateTextInvoke(ByVal new_text As String)
Public Sub UpdateText(ByVal new_text As String)
'Here the textBox.Text = ""
Dim txtB As TextBox = Me.TextBox1
'InvokeRequired always = False.
If txtB.InvokeRequired Then
Dim invk As New UpdateTextInvoke(AddressOf UpdateText)
txtB.Invoke(invk, New Object() {new_text})
Else
'The value of this text box is updated, but the text on the form TextBox1 never changes
txtB.Text = new_text
End If
End Sub
End Class
Public Class TimerTest
Private Shared tmr As New System.Timers.Timer
Private Shared counter As Integer
Public Shared Sub StartTimer()
tmr.Interval = 5000
AddHandler tmr.Elapsed, AddressOf UdpateText
tmr.Enabled = True
End Sub
Public Shared Sub UdpateText(ByVal sender As Object, ByVal e As System.EventArgs)
counter += 1
Form1.UpdateText(String.Format("Updated {0} time(s).", counter))
End Sub
End Class
SOLVED
In the Class TimerTest added this code 'Private Shared myform As Form1 = Form1'
then changed 'Form1.UpdateText' To 'myform.UpdateText'
As indicated in the comments, you are using the default form instance feature of VB.Net. You could pass an instance of the form to the TimerTest class, and replace the reference to Form1 with the instance.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim checking_text As String = Me.TextBox1.Text
TimerTest.StartTimer(Me)
End Sub
Public Sub UpdateText(new_text As String)
If TextBox1.InvokeRequired Then
Dim invk As New Action(Of String)(AddressOf UpdateText)
TextBox1.Invoke(invk, {new_text})
Else
TextBox1.Text = new_text
End If
End Sub
End Class
Public Class TimerTest
Private Shared tmr As New System.Timers.Timer()
Private Shared counter As Integer
Private Shared instance As Form1
Public Shared Sub StartTimer(formInstance As Form1)
instance = formInstance
tmr.Interval = 5000
AddHandler tmr.Elapsed, AddressOf UdpateText
tmr.Enabled = True
End Sub
Public Shared Sub UdpateText(ByVal sender As Object, ByVal e As System.EventArgs)
counter += 1
instance.UpdateText(String.Format("Updated {0} time(s).", counter))
End Sub
End Class

Timer (TimerList) fires twice even more... on deployment computer

I'm referring to this post (https://social.msdn.microsoft.com/Forums/vstudio/en-US/1bc71779-4b08-4d85-aaf1-531ed836a008/how-to-run-task-on-specified-timer-from-list-of-structure?forum=vbgeneral) but while deploying the program I realized that the Timer fires 2 or 3 times which results to open the file twice even three times.
I searched for a solution and found here (Run method every specified time within a service without repeating) one is explaining we need to use "SynchronizingObject" (https://msdn.microsoft.com/en-us/library/system.timers.timer.synchronizingobject(v=vs.110).aspx) but I'm able to apply it.
and I also noticed that sometimes the Timer is not accurate (it is short), I installed .Net 4.5.1 on deployement computer but it's still not working properly.
Can you please help?
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
StartTimer(1000, "c:\myfile1.txt")
StartTimer(1500, "c:\myfile2.txt")
End Sub
Private TimerList As New List(Of Timer)
Private Sub StartTimer(ByVal RunTime As Integer, ByVal FileName As String)
TimerList.Add(New Timer With {.Interval = RunTime, .Tag = FileName, .Enabled = True})
AddHandler TimerList(TimerList.Count - 1).Tick, AddressOf myTimer_Tick
End Sub
Private Sub myTimer_Tick(sender As Object, e As EventArgs)
Dim theUsedTimer = DirectCast(sender, Timer)
Dim runtime = theUsedTimer.Interval
Dim filename = theUsedTimer.Tag
theUsedTimer.Stop()
End Sub
End Class
The below code is the one I use on the real Program
Public TimerList As New List(Of Timer)
Public Sub StartTimer(ByVal RunTime As Integer, ByVal FileName As String)
TimerList.Add(New Timer With {.Interval = RunTime, .Tag = FileName, .Enabled = True})
AddHandler TimerList(TimerList.Count - 1).Tick, AddressOf myTimer_Tick
End Sub
==========
Public Sub myTimer_Tick(sender As Object, e As EventArgs)
Dim theUsedTimer = DirectCast(sender, Timer)
Dim runtime = theUsedTimer.Interval
Console.WriteLine(" ********************* File to open using Timer : " & theUsedTimer.Tag)
End Sub
==========
StartTimer(millisecond, FullPathfile)

Can I assign delegate sub to AddHandler using AddressOf?

Edit: my orginal question was too confusing.
Public Class PrintResults
Public Sub ResultsToPS(ByVal lis As List(Of FileData), ByVal PSPathName As String)
Me.List = lis
'setup report writer
Dim rep As New Helper.Report
'create report to PS
rep.ToPS(PSPathName)
End Sub
Public Class Report
Public Sub New()
PrintDoc = New Printing.PrintDocument
End Sub
Public WithEvents PrintDoc As Printing.PrintDocument
Public PrintDocPrintPage As PrintDoc_PrintPage
Public Delegate Sub PrintDoc_PrintPage(ByVal sender As Object, _
ByVal e As Printing.PrintPageEventArgs) 'Handles PrintDoc.PrintPage
Public Function ToPS(ByVal PSPathName As String) As String
'fails
AddHandler Me.PrintDoc.PrintPage, AddressOf Me.PrintDocPrintPage
Me.PrintDoc.Print()
End Function
AddHandler has compiler error: AddressOf operand must be the name of a method. Is there any way to assign the handler to a delegate sub?
Maybe creating events and attaching a function to it is what you are looking for.
Sub Main()
Dim c As New TestClass
AddHandler c.OnComplete, AddressOf Test
c.Execute() ' Will print Done
Console.ReadLine()
End Sub
Sub Test()
Console.WriteLine("Done")
End Sub
Class TestClass
Public Event OnComplete()
Public Sub Execute()
RaiseEvent OnComplete()
End Sub
End Class
With some research I found it's not possible to use a delegate sub with AddressOf. So we need a different approach. I see it now that all I have to do is instantiate the PrintDoc in the New sub. Now I have a PrintDoc object for the AddHandler to use.
Public Class Report
Public Sub New()
PrintDoc = New Printing.PrintDocument
End Sub
We use the regular AddHandler with no delegates:
Public Class PrintResults
Public Sub ResultsToPS(ByVal lis As List(Of FileData), ByVal PSPathName As String)
Me.List = lis
'setup report writer
Dim rep As New Helper.Report
'PrintDoc is automatically instatiated so no object error
AddHandler rep.PrintDoc.PrintPage, AddressOf Me.PrintDoc_PrintPage
'create report to PS
rep.ToPS(PSPathName)
End Sub
Delegates and the AddressOf Operator
AddHandler Statement

Move image from picturebox to another picturebox in another form

im trying to move an image from a PictureBox to another PictureBox in another Form that was captured by a WebCam, but my code is not working.
Public Class Form12
Private _capture As Emgu.CV.Capture
Private _captureInProgress As Boolean
Dim form23 As Form23
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
form23.SetPictureBoxImage(captureImageBox.Image)
form23.Show()
End Sub
Private Sub captureButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles captureButton.Click
If (_capture Is Nothing) Then
Try
_capture = New Emgu.CV.Capture
Catch excpt As NullReferenceException
MessageBox.Show(excpt.Message)
End Try
End If
If (Not _capture Is Nothing) Then
If _captureInProgress Then
Me.captureButton.Text = "Start Capture"
RemoveHandler Application.Idle, New EventHandler(AddressOf Me.ProcessFrame)
Else
captureButton.Text = "Capture"
AddHandler Application.Idle, New EventHandler(AddressOf Me.ProcessFrame)
End If
_captureInProgress = Not _captureInProgress
End If
End Sub
Private Sub ProcessFrame(ByVal sender As Object, ByVal arg As EventArgs)
Dim frame As Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte) = Me._capture.QueryFrame
Dim grayFrame As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) = frame.Convert(Of Emgu.CV.Structure.Gray, Byte)()
Dim smoothedGrayFrame As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) = grayFrame.PyrDown.PyrUp
captureImageBox.Image = frame.Bitmap
End Sub
Private Sub ReleaseData()
If (Not _capture Is Nothing) Then
_capture.Dispose()
End If
End Sub
2nd Form
Public Class Form23
Public Sub SetPictureBoxImage(ByVal image As Bitmap)
PictureBox1.Image = image
End Sub
End Class
all the webcam thing is working, just the transfer of image is not. sorry just a newbie here. just got this codes from a tutorial.Thanks!
Forms are classes - it says so at the top of all of them:
Public Class Form817
So, an instance of them should be created and thats is what your code should use everywhere:
Dim myFrm As Form817 ' DECLARES the variable
myFrm = New Form817 ' Initialize myFrm as an instance of Form817
' short method:
Dim myFrm As New Form817
The problem is here:
form23.SetPictureBoxImage(captureImageBox.Image)
form23.Show()
VB is not case sensitive AND your code did not create and instance, so the first line is referencing the class, not the instance. When you normally do something like Form23.Show - without creating an instance, VB creates one for you with the same name. This is called the default form instance and should be avoided (always).
Your image transfer fails because the code references one thing (Form23), but another is shown (a new instance of Form23).

VB Net - Pass data from Thread to Main GUI

I've managed to get the data I want in a thread, however I'm having trouble getting my head around passing the data back into my main thread (GUI).
I'm grabbing data from a network stream in a thread, then need to pass it to my main thread in order to pass to other classes etc.
I've seen it mentioned to use backgroundworker for this, but as I'm expecting it to gather data periodically and never stop, I thought a separate thread for this would be best, but I'm very new to multithreading.
If threading is the correct way to go, how can I pass data from it back to my main thread in order to use this for other stuff? I've seen delegates and events mentioned a lot but can't see how I'd pass data with these?
Thanks
Please study this example, and let me know if it fits your requirements:
Controls required: lstItems (ListBox), btnStart (Button), btnStop (Button), Timer1 (Timer).
Form1 code:
Public Class Form1
Dim p_oStringProducer As StringProducer
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
p_oStringProducer = New StringProducer
p_oStringProducer.Start()
Timer1.Enabled = True
End Sub
Private Sub btnStop_Click(sender As Object, e As EventArgs) _
Handles btnStop.Click
Timer1.Enabled = False
p_oStringProducer.Stop()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim asQueue As Concurrent.ConcurrentQueue(Of String) =
p_oStringProducer.MessageQueue
While asQueue.Count > 0
Dim sItem As String = Nothing
asQueue.TryDequeue(sItem)
lstItems.Items.Add(sItem)
End While
End Sub
End Class
StringProducer code:
Imports System.Threading.Tasks
Public Class StringProducer
Private p_fKeepRunning As Boolean
Private p_oTask As task
Private p_aMessageQueue As Concurrent.ConcurrentQueue(Of String)
Private p_iNextMessageId As Integer
Public ReadOnly Property MessageQueue As _
Concurrent.ConcurrentQueue(Of String)
Get
Return p_aMessageQueue
End Get
End Property
Sub New()
p_oTask = New Task(AddressOf TaskBody)
p_aMessageQueue = New Concurrent.ConcurrentQueue(Of String)
p_iNextMessageId = 0
End Sub
Public Sub Start()
p_fKeepRunning = True
p_oTask.Start()
End Sub
Public Sub [Stop]()
p_fKeepRunning = False
End Sub
Private Sub TaskBody()
While p_fKeepRunning
Threading.Thread.Sleep(2000)
p_aMessageQueue.Enqueue("Message #" & p_iNextMessageId)
p_iNextMessageId += 1
End While
End Sub
Protected Overrides Sub Finalize()
MyBase.Finalize()
Me.Stop()
End Sub
End Class
This was not extensively tested, but it should give you a head start.