Replacing my function with a better one - vb.net

i'm trying to popup a msgbox everytime the current time is equal to a field in a table in the database i'm using the following code:
For i As Integer = 0 To contentTable.Rows.Count() - 1
UpdateListBoxRec2("Sending content " & i + 1 & " to :")
For j As Integer = 0 To subTable.Rows.Count() - 1
While send = False
If contentTable.Rows(i).Item(1) = DateTime.Now.ToString("hh:mm") Then
UpdateListBoxRec2(subTable.Rows(j).Item(0))
MsgBox(contentTable.Rows(i).Item(0))
send = True
End If
End While
'send = False
Next
Next
this method works but when the debugger is in the while loop ( means when the current time is not yet equal to the time i have in my db table ) i can't use any tool of my windows app untill the debugger gets out of the while loop so i'm searching for a similar method to popup my msgbox in the same condition and to be able to use my tools in the app all the time
please note that i'm using vb.net
any help please :)

You should never sit in an endless loop, like that, on the UI thread. As long as the UI thread is busy, it will be blocked from processing any incoming window messages (e.g. key strokes, mouse clicks). You could sit in a loop like that if you were on a separate thread, but that would be silly. The more sane solution would be to use a timer. For instance, if you drop a Timer component onto your form in the designer, and set it's Interval property to 5000 (five seconds), you can then add the following code:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
For i ...
For j ...
If contentTable.Rows(i).Item(1) = DateTime.Now.ToString("hh:mm") Then
UpdateListBoxRec2(subTable.Rows(j).Item(0))
MessageBox.Show(contentTable.Rows(i).Item(0))
End If
Next
Next
End Sub
Now it will just run that code once every five seconds rather than continuously checking the current time and thereby hogging the UI thread.

Related

Visual Basic: Image moves up and and then back down after a button click

I am attempting to make a character appear to jump straight up in the air and then come back down and return to the same level he started at. (y=100) The code below seems to make the program fight itself and move him up and down at the same time.
I have tried countless methods and all of them resulted in the guy either going up and not coming back down or flying off the page.
Private Sub btnJump_Click(sender As Object, e As EventArgs) Handles btnJump.Click
tmrJump.Start()
End Sub
Private Sub tmrJump_Tick(sender As Object, e As EventArgs) Handles tmrJump.Tick
For intCounterUp As Integer = 100 To 15
picSpaceRunner.Location = New Point(intCounterX, intCounterY)
intCounterY = intCounterUp
Next intCounterUp
For intCounterDown As Integer = 15 To 100
picSpaceRunner.Location = New Point(intCounterX, intCounterY)
intCounterY = intCounterDown
Next intCounterDown
End Sub
End Class
The code is running with no delay, so you're at the mercy of the machine.
I'm not a professional game coder, so I couldn't explain the intricacies of modern game engines. However, one of the basic ideas I learned a long time ago is to control your game/animation loop. Consider the frames per second.
In your code, it could be as simple as adding a delay within each loop iteration. If you want the character to complete his jump in 2 seconds (1 second up, 1 second down), then divide 1000 (1 sec = 1000 ms) by the number of iterations in each loop and delay by that amount. For example, you have 85 iterations, so each iteration would take approximately 12 ms.
If you don't mind blocking a thread, you can do this very easily with Threading.Thread.Sleep(12). If blocking is an issue, you'll likely want to use an external timer.
I found this link during a Google search. He explains how to set up a managed game loop in VB.Net.
http://www.vbforums.com/showthread.php?737805-Vb-Net-Managed-Game-Loop
UPDATE: Per OP's comment...
To do this using timers, you'll want to manipulate the character object directly within the Timer event handler (Tick). You wouldn't use loops at all.
Set the Timer's Interval to the value discussed earlier - the number of ms corresponding to how long it takes to move 1 pixel. Then, in the Timer's Tick handler, set the character object's Location equal to a new Point with the new value. Also in the Tick handler, check your upper bound (15), then reverse the process until it hits the lower bound (100).
For example,
Private Sub tmrJump_Tick(sender As Object, e As EventArgs) Handles tmrJump.Tick
If (intCounterY > 15 And blnGoingUp == True) Then
picSpaceRunner.Location = new Point(intCounterX, intCounterY - 1);
End If
... Remaining Code Goes Here ...
End Sub
Do not put the loop in the timer_tick. Increase or decrease the height by set interval instead and then check if the image had reached the maximum or minimum height.

Vb.net How can I sleep between multiple tasks in a sub

Figured my previous attempt in doing this question was too opinion based, so I'll be more specific.
Intro:
I'm trying to best way possible sleep inbetween multiple "tasks" within a private sub, but my attempts so far have failed me.
I have 9 "tasks" being triggered by a timer timermain and a progressbar pbmain that are working together. At pbmain.value 10 task 1 is being triggered, at pbmain.value 20 task 2 is being triggered and this goes all the way up to pbmain.value 100 and at that point it sets value to 1 and then this whole process loops over and over.
The problem is that this way is not very accurate because some of the tasks take more time than the others, so I'd much rather like to somehow sleep/pause/wait a second or so between each task than use progressbar value.
This is what it looks like
Private Sub TimerMain_Tick(sender As Object, e As EventArgs) Handles TimerMain.Tick
pbMain.Increment(1)
'Channel 1
If cbc1.Checked = True Then
If pbMain.Value = 10 Then
Try
Dim fileTotal As Integer
For Each item As String In lbChannel1.Items
fileTotal += My.Computer.FileSystem.GetFiles(item.ToString, FileIO.SearchOption.SearchTopLevelOnly, (tbExt1.Text)).Count
Next
tbCount1.Text = String.Format("{0}", fileTotal.ToString)
Catch ex As Exception
lbErrors.Items.Add(String.Concat(TimeOfDay & " Error 001: ", ex.Message)) 'Error output
End Try
End If
End If
'Channel 2
'... same as above. Then channel 3, 4, 5, 6, 7, 8 and 9...
To clarify what this does and the whole purpose:
I have so called channels in my form. Each channel is a listbox with items that are paths like \server\share\folder. The code above counts files in those folders if checkbox for that specific channel is checked and gives number output to a textbox tbcount1-9. So yes, the application is monitoring files going in and out of specified folders.
My goal:
Do task 1 -> Complete task 1 and wait one second -> Move to task 2 -> repeat this all the way to task 9 and then loop
I've tried:
Perform step. Did not work well because it looped too fast and fast out of control. I removed pbmain.increment and used performstep between each task.
Thread.sleep. This caused the whole application to sleep for given amout of time instead .
Progressbar marquee mode. I tried, but couldn't figure out how to make it work like my goal.
My question:
How can I complete my goal using something else than progressbar value with a timer...?
Update
Alexander's comment answered my question
You can try with Asnyc/Await Asynchronous Programming with Async and Await
Since your task are working with IO - async/await will be best approach.
Starting new thread only for waiting result from IO is waste of resources(threads).
Private Async Function ExecuteAllAsync() As Task
While True
Await ExecuteTasksAsync()
End while
End Function
Private Async Function ExecuteTasksAsync() As Task
Dim task1 As Task = ExecuteTaskNumberOneAsync()
Await Task.Delay(1000)
Dim task2 As Task = ExecuteTaskNumberTwoAsync()
Await Task.Delay(1000)
'... and so on
'Then wait for all results
Await Task.WhenAll({task1, task2, ...})
End Function
Here is only an idea - of course code above can/must be refactored to "usable" way
Are you just looking for a simple 1 second delay? If so.
Dim Current_Time as Date=Now
While DateAdd(DateInterval.Second, 1, Current_Time)>Now
End While
Now returns the current Date and Time
So I guess your flow would be
Task1->
Delay 1 Sec->
Task 2

Multithreading in vb.net to simulate task

I have a program that is doing one task.
For Example i have one list box containing some links.
And on the other hand my program is opening them one by one but i want it to be done faster
i have used for-each loop for that purpose.
All what i want to do is i wanna give every 2 or 3 link to a different thread or if there is any other solution to make it Faster Kindly tell me.
This is a small piece of code from my program.
For value As Integer = 1 To TextBox1.Text
If (value = TextBox1.Text) Then
Exit For
End If
Dim page As String = "-p-" & value
Extractor.ScrapLinks(txturl.Text + page, lstbox)
lbllinks.Text = lstbox.Items.Count
Next
I don't know what Extractor.ScrapLinks actually do, but it seems that you need to access UI thread and you cannot create multiple UI threads so eventually you will process them sequentially
What you can do to improve the solution is to read the data you want from the UI controls and then process that data on a separate thread, after completion you can fill the results into the UI by invoking some method on the UI thread as shown below
Delegate Sub PerformOperationDel(value As Integer)
Sub PerformOperation(value As Integer)
Dim page As String = "-p-" & value
Extractor.ScrapLinks(txturl.Text + page, lstbox)
lbllinks.Text = lstbox.Items.Count
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For value As Integer = 1 To CInt(TextBox1.Text) - 1
lstbox.BeginInvoke(New PerformOperationDel(AddressOf PerformOperation))
Next
End Sub
You can use backgroundworkers but notice that you cannot access UI controls in the DoWork but you can access them on work completed (Refer to: Background worker proper way to access UI)
Best of luck

How can I get a program to run automatically at specific times a day (VB.NET)

The application I'm developing right now allows the user to update an Excel sheet or Sql database for set metrics twice a day. The program does this by popping up at certain times (e.g. 6:00 AM, 5:00 PM, 3:42 PM, whatever the user sets). By having the program pop up at certain times, the program ("Auto Excel It!!!") allows you as the user to track set data (say, sales calls, sales presentations, meetings, number of hours coding, number of jalepeƱo burritos eaten, etc.).
How can a developer get this program to "pop up"/start/function automatically at specific times through the means of the Windows Scheduler API (or something better)?
Here's how my understanding's evolved lately:
Nothing --> Use Timers As The Program Runs In The Background --> Use Windows Scheduler's API To Run Automatically (Current) --> Possible New Understanding From Your Answer
For example, I'm aware of: DispatcherTimers, Timers, another timer I'm not aware of, Sleep(), Windows Scheduler. But with these in mind, I don't know what to do regarding the following: Automatically starting a program via Windows Scheduler; Preserving computer resources if a timer is used; or even how to get this top pop up automatically.
Update 1:
#nfell2009:Your logic helped me out big time. At first I had to toy around with converting your Timer here to a DispatcherTimer (WPF forms standard, it seems). Then, I switched the the "Handles" for the Sub tCheckTime to "AddHandler tCheckTime.Tick, AddressOf tCheckTime_Tick" --- Why I had to do this is a good question.
Then, once I had the basic EventHandlers set up, your idea for comparing the user's text (As Date) to the System.Date is good--When I screwed something up and couldn't get the code to work, I switched it up and converted System.Date to a String--i.e. I went from String->Date To Date->String... That's when I got the Timer to work. When my System.Time ticked to 3:12 PM, the MsgBox popped up with "Your Message Here."
(A Quick (Evil) Thank You! I've spent four-plus hours getting this to work)
Code:
From Using "Handles" At tCheckTime_Tick (Which seems like it 'should' work)
Private Sub tCheckTime_Tick(sender As Object, e As EventArgs) Handles tCheckTime.Tick
...
End Sub
To AddHandler blah, AddressOf tCheckTime_Tick (Does work)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Loaded
'MsgBox(Now().ToString("hh:mm")) 'String.Format("{hh:mm}", Now()))
AddHandler tCheckTime.Tick, AddressOf tCheckTime_Tick 'Why is this necessary?
tCheckTime.Interval = New TimeSpan(0, 1, 0)
End Sub
Public Class Form1
Dim iSetTime As Date
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub btnSetTime_Click(sender As Object, e As EventArgs) Handles btnSetTime.Click
If (tCheckTime.Enabled = True) Then
tCheckTime.Enabled = False
End If
iSetTime = txtTHour.Text + ":" + txtTMinute.Text + ":" + txtTSecond.Text
tCheckTime.Enabled = True
End Sub
Private Sub tCheckTime_Tick(sender As Object, e As EventArgs) Handles tCheckTime.Tick
If (TimeOfDay = iSetTime) Then
MsgBox("Your Message")
End If
End Sub
End Class
You will need error checking for the textboxs, but its simply:
3 textboxs with indication of which is which, so maybe a label each with H, M, S - or something.
A button which will set time and a timer. Naming:
Textboxs
Hours = txtTHour
Minutes = txtTMinute
Seconds = txtTSecond
Buttons
Start Button = btnSetTime
Timers
Timer = tCheckTime
I can think of two easy ways:
Have your program calculate the time until it should next appear in seconds and then set a timer with an elapsed time such that when the tick event is raised you can do whatever you need to do.
Use MS Task Manager to launch your program when and as needed.

Label.Text doesn't change in a loop

I'm trying to change a text that a label displays during each iteration of a Do While loop in Visual Basic. One label (which displays an integer) works fine, however the other stays blank until the loop finishes and displays the final result. What could be the problem?
Private Sub btnCalc_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles btnOblicz.Click
Dim W As Single
Dim L As Integer
Dim J As Integer
Dim Y As Double
W = Val(txtW.Text)
L = InputBox("Input L")
J = 0
If W > 0 And W < 100 Then
Do
Y = (2 * Math.Sqrt(W)) / (L - J)
J = J + 1
lblJ.Text = Str(J)
lblY.Text = Str(Y)
MsgBox("Next...")
Loop Until Y < 0
Else
MsgBox("No calculations, because the number is less than zero or greater than a hundred.")
End If
End Sub
Application.DoEvents(), as suggested by others, can work. However, you should be aware that it has some negative side-effects, such as the potential to create StackOverflowExceptions.
The right way to solve this problem is to use a BackgroundWorker component.
As to why this happens... remember that all windows programs work by having, at their core, a loop which checks for messages from the user and operating system (things like mousemove events, clicks, keystrokes, etc). When you set the text property of a label, you are not telling the label to re-draw itself on the screen. Instead, you are posting an event to the operating system that your program's message loop must then receive and process. As new events come in, the message loop (or pump) sends those events to the proper method.
Your btnCalc_Click() function is one such method. If your function is running, it was called by the core windows messaging loop, which is now waiting for your method to complete and return control: it's blocked. The loop cannot continue receiving and dispatching methods until your function completes, and therefore nothing in your program's interface can be updated.
This worked fine for me in small copy I did using VS2010
It may be that a message pump is required. Try this :
System.Windows.Forms.Application.DoEvents()
Probably, your window function which processes OS event message is inaccesible while your loop executes. Try explicitly call dispatching messages. E.g. insert after assigning labels text inside your loop
Application.DoEvents