Why won't my code Loop? - vb.net

Sorry for the messy code :S
If CheckBox2.Checked = True Then
For i As Integer = 0 To 1 Step 0
If CheckBox1.Checked = True Then
If TextBox1.Text = lblCLickLImit.Text Then
Timer1.Stop()
TextBox1.Text = "0"
System.Windows.Forms.SendKeys.Send("{F5}")
System.Threading.Thread.Sleep(delaydelaytime)
System.Windows.Forms.SendKeys.Send("{ENTER}")
Else
If CheckBox1.Checked = False Then
If TextBox1.Text = lblCLickLImit.Text Then
Timer1.Stop()
TextBox1.Text = "0"
End If
End If
End If
Else
If CheckBox2.Checked = False Then
If CheckBox1.Checked Then
If TextBox1.Text = lblCLickLImit.Text Then
Timer1.Stop()
TextBox1.Text = "0"
System.Windows.Forms.SendKeys.Send("{F5}")
System.Threading.Thread.Sleep(delaydelaytime)
System.Windows.Forms.SendKeys.Send("{ENTER}")
End If
Else
If CheckBox1.Checked = False Then
If TextBox1.Text = lblCLickLImit.Text Then
Timer1.Stop()
TextBox1.Text = "0"
End If
End If
End If
End If
End If
Next
Basically this code is for an Auto Clicker program,(Hopefully this will help you understand, http://prntscr.com/7tuc3o interface) Ok so when the "Continuous" checkbox is selected the code is in theory supposed to loop for infinity. However when I run the program with everything selected as shown all that happens is the program clicks once and then crashes (not responding). Any help I have tried this loop in other programs and it works, just not with this code.

Your loop is tying up the UI thread. You'll need to look into using either a background worker:
BackgroundWorker handles long-running tasks. It does not freeze the entire program as this task executes.
(dotnetperls.com)
Here is the msdn walkthrough of how to set-up a backgroundworker:
https://msdn.microsoft.com/en-us/library/ywkkz4s1.aspx
Or
If this is a personal project and no one you love will need to maintain this code, you can use Application.DoEvents() to continue to pump messages while the program is looping. Here is the msdn documentation for that https://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents(v=vs.110).aspx

First of all, a Step of 0 doesn't really make any sense in a for loop. It may /work/ but it is going to drive anyone reading it later insane. If you want an infinite loop don't use a for loop, use:
While True
'code here
End While
For loops are used when you know exactly how many iterations of your loop you need. A while loop is designed to iterate as long as some condition is true. In this example the condition is always true so it loops indefinitely.
Your code is also just going to spin the UI thread constantly. It never pauses for input (even your sleep calls do not release the thread for input). As far as the OS knows, your app has locked up because it never processes any of the window messages that get posted to it. It is still happily spinning away though, until windows finally gets tired of it and prompts you to kill it.

Not sure what other "programs" you're working with but I can tell you you don't want to use a For loop for this. You want a do/while loop, like either:
While True
...
End While
or
Do
...
Loop While True

Related

Want to display the processing progress using a Label to show a counter of sorts

Its a label printing app. Desire to show progress via a counter displaying in a Label. ie. would like it to
look like this... 1000 increments to 1001 increments to 1002, 1003 etc. Pretty simple pgm so obviously processing from start to finish is instantaneous. Thus end number pops up right away rather than flashing a sequence of sorts. Don't need number to be readable but just simulating the process. Since it is a printing program, there is time for this display. At the end of processing the final number should be on the screen. Thought maybe I could use a timer to tick off before updating label. My coding is obviously not correct. Here it is. Any suggestions are appreciated. I am a 79 YO tinkerer programmer (worked back in the COBOL days) so be kind LOL.
Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles Button2.Click
' Print button
Dim toPrint As Integer = Me.NumericUpDown2.Value
Dim RetVal As Object
Dim TopPos As String = "375,200"
Dim InfoPos As String = "360,260"
startNo = TextBox2.Text
For index As Integer = 1 To toPrint
RetVal = RDP.PrintRawData("^XA^LL450^PQ" & arrCust(4) & "^CFB,30^FO" & TopPos & "^FD" & arrCust(5) & StartNo & "^FS^FO" & InfoPos & "^FD" & arrCust(2) & "^FS^XZ")
Timer1.Interval = 1000
Timer1.Start()
startNo += 1
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label4.Text = startNo
End Sub
The problem is the loop never yields control back to the underlying windows event message pump, and so there's never a chance to process any paint messages to redraw the label until after everything is finished.
To fix this we first need to resolve two conflicting statements:
from start to finish is instantaneous
and
Since it is a printing program, there is time for this display.
Only one of those two statements can be true. They are mutually exclusive.
If the first statement is true, I'd change the timer to tick more often (every 200 milliseconds or so; faster is just wasteful) and put up with an ugly Application.DoEvents call in the loop so the label can have a chance to repaint. (Also: start the timer once, before entering the loop, and not on each iteration).
If the latter statement is true, I'll echo the usual warnings about avoiding Application.DoEvents (there are a lot of "gotchas" with this method). Instead, I'd do it the right way, and use a BackgroundWorker component.

Progess bar in vb.net 2008 while File loading into the grid

I have written in vb.net for progress bar. I am thinking of there is a better way than this.
Here is what my code is :
Private Function ImportDataFiles(ByRef pobjDataLoadDTO As DataLoadDTO) As Boolean
Try
lblStatus.Visible = True
lblStatus.Text = ""
myProgressBar.Visible = True
myProgressBar.Value = 0
For Each drRow As ImportData.TRow In pobjDataLoadDTO.FileInfo.Select("categ_code = 'abc'")
If pobjDataLoadDTO.FileTimes.ContainsKey(drRow.KEY_CODE) AndAlso _
pobjDataLoadDTO.FileTimes(drRow.KEY_CODE) > pobjDataLoadDTO.UploadTimes(drRow.KEY_CODE) Then
pobjDataLoadDTO.DestinationTablename = drRow.KEY_CODE
If mobjDataLoadBO.ImportDataFiles(pobjDataLoadDTO) Then
drRow.DATA_TXT = mobjCommonBO.ONow.ToString
End If
End If
lblStatus.Text = drRow.KEY_CODE.Trim & "is loading...."
lblStatus.Refresh()
myProgressBar.PerformStep()
lblStatus.Refresh()
Next
Return True
Catch ex As Exception
Return False
End Try
End Function
Right now It is working, But I want to use more efficient way, like using Backgroundworkerprocess...etc., Any Ideas on this one?
Since your function runs in main thread, I assume your application is freezing and not very smooth while upload in progress.
1 - Drop Backgroundworker control on the form
2 - set "reportProgress" property of the worker to "True"
3 - Move your loop code into "DoWork" event of the worker control. And call worker.RunWorkerAsync. You can pass needed arguments to it
4- the code that refreshes progress bar move into "ProgressChange" event of the worker. This is important as you can't call control from worker thread. and ProgressChange is running in the main thread. You can also delete "Refresh" method call. That will not be needed anymore. Every time you want to refresh the progress bar call "ReportProgress" method of the worker
5-Use "RunWorkerCompleted" worker event, to do your clean up, and hide your progress bar
Its also might be a good idea to check if worker is already working before initiating, like
If worker.IsBusy Then
If worker.CancellationPending = False Then
worker.CancelAsync()
End If
Exit Sub
End If

Reduce thread CPU usage

So I have 2 threads in my application which work fine except for the fact that they will continue taking up rather large amounts of my processor even after they are closed or aborted. This is how one of the loops look like along with some of the main declarations.
Dim Thread1 As System.Threading.Thread
Dim ThreadRunning As Boolean
Dim Thread1Running As Boolean = False
Sub Something()
While True
If ThreadRunning = True Then
Try
...Actions which don't necessarily affect the thread
Catch ex As Exception
End Try
ElseIf ThreadRunning = False Then
If Thread1Running = True Then
Thread1Running = False
Thread1.Abort()
Else
End If
End If
End While
End Sub
Here is the code I used to start the thread.
Thread1Running = True
Dim Thread1 As New System.Threading.Thread(AddressOf Something)
Thread1.IsBackground = True
Thread1.Priority = ThreadPriority.Lowest
Thread1.Start()
Here is the code I use to stop the thread.
ThreadRunning = False
The actions in the thread need threads since timers were too slow for the task(even at a 1 ms interval). The actions are performed fine except for when I abort the thread. In this case the thread will close and the CPU usage will go from around 25% to 0% for this program but then it will crash with a CLR error. When I aborted the thread from outside the sub it would still leave the program CPU usage at 25% which is what I'm trying to avoid. So my main question is: Is it possible to close the thread and reopen it later without it crashing, and so that while it is closed it won't use up 25% of the CPU(or some other rather high CPU performance)? If this isn't enough information I will provide more but I thing this will suffice... hopefully. Thanks for any help.
Here's the solution I found which worked.
While True
If ThreadRunning = True Then
Try
...Code stuff
Catch ex As Exception
End Try
ElseIf ThreadRunning = False Then
Exit While
End If
End While
Exit Sub
Apparently checking it this way made it so that 1. The thread doesn't hang. 2. It fully exits the thread and prevents it from using the CPU while closed. And 3. It allows for reusing the threads through the same method as shown above.

Unload/Remove vb Resource from Memory

I'm extremely new to programming and have still to master a lot of the basics. But I've managed to make an entire Program with help from here and there. However, I think I've got a Memory Leak with regards to my resources, again I'm new and almost certain this is a clumsy way to go about doing this...
I currently have background music in my application which uses a .wav file stored in My.Resources. I've implemented multiple measures to enable, disable and mute the audio successfully, but I've hit a snag when I introduced multiple audio tracks. The idea is to give the end-user an option between 4 background songs (stored as 4 .wav resources) in the 'settings' area of my program. When I build & test the solution it runs great, everything as expected. Then when I change the audio to a different track in the settings area, it works also. The snag happens when I change the song multiple times, I get a OutOfMemory error.
I think I understand what's happening; the resource is being added to the memory each time the user selects it, But I have no idea on how to remove -say- song1 from the memory if -say- song2 is selected. Here's my code which handles the selection & playing of the audio.
(The program uses radio buttons refereed to as '%chkbox' and requires the user to hit 'savebtn' before this code is ran.) Using Visual Basics 2012 .net 4.5
'Save and start songs.
If DjErhain_Mistychkbox.Checked = True Then
My.Settings.AudioDJErhain_UWBeats_Maniac = 0
My.Settings.Save()
My.Settings.AudioDjErhain_Misty = 1
My.Settings.Save()
My.Settings.AudioMachinimaSound_Exigence = 0
My.Settings.Save()
My.Settings.AudioSimplex_Memories_master = 0
My.Settings.Save()
My.Computer.Audio.Play(My.Resources.DjErhain_Misty, AudioPlayMode.BackgroundLoop)
ElseIf DJErhain_UWBeats_Maniacckbox.Checked = True Then
My.Settings.AudioDjErhain_Misty = 0
My.Settings.Save()
My.Settings.AudioDJErhain_UWBeats_Maniac = 1
My.Settings.Save()
My.Settings.AudioMachinimaSound_Exigence = 0
My.Settings.Save()
My.Settings.AudioSimplex_Memories_master = 0
My.Settings.Save()
My.Computer.Audio.Play(My.Resources.DJErhain_UWBeats_Maniac, AudioPlayMode.BackgroundLoop)
ElseIf MachinimaSound_Exigencechckbox.Checked = True Then
My.Settings.AudioMachinimaSound_Exigence = 1
My.Settings.Save()
My.Settings.AudioDJErhain_UWBeats_Maniac = 0
My.Settings.Save()
My.Settings.AudioDjErhain_Misty = 0
My.Settings.Save()
My.Settings.AudioSimplex_Memories_master = 0
My.Settings.Save()
My.Computer.Audio.Play(My.Resources.MachinimaSound_Exigence, AudioPlayMode.BackgroundLoop)
ElseIf Simplex_Memories_masterchckbox.Checked = True Then
My.Settings.AudioSimplex_Memories_master = 1
My.Settings.Save()
My.Settings.AudioDJErhain_UWBeats_Maniac = 0
My.Settings.Save()
My.Settings.AudioDjErhain_Misty = 0
My.Settings.Save()
My.Settings.AudioMachinimaSound_Exigence = 0
My.Settings.Save()
My.Computer.Audio.Play(My.Resources.Simplex_Memories_master, AudioPlayMode.BackgroundLoop)
Else
End If
Yes, this is likely to go wrong, the .wav format is not very compact. When you put it in a resource then using the resource is going to create an UnmanagedMemoryStream. It should be disposed when you don't use it anymore, the garbage collector won't run often enough to keep you out of trouble.
Add a new Module to your project and paste this code:
Imports System.IO
Module PlayerUtilities
Private CurrentStream As WeakReference(Of Stream)
Public Sub PlayResource(wave As Stream)
My.Computer.Audio.Play(wave, AudioPlayMode.BackgroundLoop)
Dim oldwave As Stream = Nothing
If CurrentStream IsNot Nothing AndAlso CurrentStream.TryGetTarget(oldwave) Then
oldwave.Dispose()
End If
CurrentStream = New WeakReference(Of Stream)(wave)
End Sub
End Module
And replace your calls to My.Computer.Audio.Play() with PlayResource(). The Dispose() call in this method on the previous audio stream will keep you out of trouble.

While loop causes the app to go slow? Any idea why?

I have a simple code that looks up a text file, reads the line of text, splits the string by semi-colons and then posts the results.
After it has done this, I have created a really simple while loop to waste 10 seconds before going for it again.... here is the code:
Private Sub checkTemps()
While Abort = False
Try
fileReader = New StreamReader(directory.Text & "currentTemp.dat")
rawData = fileReader.ReadLine()
fileReader.Close()
Dim dataArray() As String
dataArray = rawData.Split(";")
updateOutput("1", dataArray(0), dataArray(1))
updateOutput("2", dataArray(2), dataArray(3))
updateOutput("3", dataArray(4), dataArray(5))
updateOutput("4", dataArray(6), dataArray(7))
stpWatch.Start()
While stpWatch.Elapsed.Seconds < 10 And Abort = False
pollInterval(stpWatch.ElapsedMilliseconds)
End While
stpWatch.Stop()
stpWatch.Reset()
Catch ex As Exception
msgbox("oops!")
End Try
End While
closeOnAbort()
End Sub
But when it gets to the "time-wasting" loop - it seems to slow the whole application down? And I can't work out why!
So a couple of questions... is there a better way to do all this? and second - can anyone spot a problem?
All the other commands seem to run fine - there isn't much else to this app. I have another program that updates the dat file with the values, this is simply a client side app to output the temperatures.
Any help would be appreciated.
Andrew
More info:
I should explain what the pollInterval sub does!
Private Delegate Sub pollIntervalDelegate(ByVal value As Integer)
Private Sub pollInterval(ByVal value As Integer)
If Me.InvokeRequired Then
Dim upbd As New pollIntervalDelegate(AddressOf pollInterval)
Me.Invoke(upbd, New Object() {value})
Else
ProgressBar1.Value = value
End If
End Sub
Your loop is a very tight loop continually calling pollInterval. This will tie up the application until the loop condition is met.
You should use the Sleep method to pause this thread for the required amount of time.
If you want to show the progress (as per your update) you could put the Sleep into the loop and sleep for 1 second (or half a second?) at a time:
While stpWatch.Elapsed.Seconds < 10 And Abort = False
Sleep(1000) <-- NOT 100% sure of the syntax here,
but the time is specified in milliseconds
pollInterval(stpWatch.ElapsedMilliseconds)
End While
You should go with
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10).TotalMilliseconds);