Using a For/Next loop to 'kill time'

Joined
Aug 23, 2006
Messages
7
Location
Northwestern North Carolina
Programming Experience
1-3
Hello all!

I think I've put this thread in the right place.

I want to use a for/next loop to take up a predetermined length of time before a statement executes, but I haven't gotten the results I want. My code is:
__________
Private Sub runButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles runButton.Click

runButton.Enabled = False
myMessageLabel.Visible = True

For intCounter = 1 To 900000000 ' (about 2.66 seconds)
Next intCounter

myPictureBox.Visible = True
runButton.Enabled = True

For intCounter = 1 To 90000000 ' (about .44 seconds)
Next intCounter

myPictureBox.Visible = False
myMessageLabel.Visible = False

End Sub

__________
Nothing above the first loop executes properly. I've used for/next to eat up time in QBasic, but do I need another method here?

As always, any and all help would be very much appreciated!

ToasterAsString
 

Raven65

Well-known member
Joined
Oct 4, 2006
Messages
305
Programming Experience
3-5
While creative, this is definitely not the method you want to use. The biggest problem is that some PC's will process this faster than others, and that this approach will take more or less time depending on system load.

A better approach, I believe, is to use Timers.

I'm not the biggest fan of the following (because of the needs for the DoEvents) and am sure there is a better way, but this functions.

VB.NET:
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class[/COLOR][/SIZE][SIZE=2] Form1[/SIZE]
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Form1_Load([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=2].Load[/SIZE]
[SIZE=2][COLOR=#0000ff] Me[/COLOR][/SIZE][SIZE=2].Show()[/SIZE]
[SIZE=2][COLOR=#0000ff] Me[/COLOR][/SIZE][SIZE=2].Timer1.Interval = 10000[/SIZE]
[SIZE=2][COLOR=#0000ff] Me[/COLOR][/SIZE][SIZE=2].Timer1.Enabled = [/SIZE][SIZE=2][COLOR=#0000ff]True[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff] Me[/COLOR][/SIZE][SIZE=2].Timer1.Start()[/SIZE]
[SIZE=2][COLOR=#0000ff] While[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].Timer1.Enabled = [/SIZE][SIZE=2][COLOR=#0000ff]True[/COLOR][/SIZE]
[SIZE=2]   Application.DoEvents() [/SIZE][SIZE=2][COLOR=#008000]'While loop is on GUI thread. DoEvents to prevent whiteout.[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff] End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]While[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff] Me[/COLOR][/SIZE][SIZE=2].Label1.Text = [/SIZE][SIZE=2][COLOR=#800000]"asdf"[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Timer1_Tick([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] Timer1.Tick[/SIZE]
[SIZE=2][COLOR=#0000ff] Me[/COLOR][/SIZE][SIZE=2].Timer1.Enabled = [/SIZE][SIZE=2][COLOR=#0000ff]False[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class[/COLOR][/SIZE]

That would give a 10 second delay before setting the Label1 to "asdf". You could after that, reset the timer interval to the next desired wait, re-enable the timer and start it again for the second delay.
 
Last edited:

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,609
Location
Norway
Programming Experience
10+
Timer is also unreliable in the run, if system is busy it will skip a second every now and then, at least that's what I have experienced. To overcome this you can save the starting DateTime (Date.Now) and loop until any current Date.Now subtracting the start is around the TimeSpan targeted. Example:
VB.NET:
Sub timeout(ByVal seconds As Integer)
    Dim start As Date = Date.Now
    Do Until Date.Now.Subtract(start).Seconds >= seconds
        Application.DoEvents()
        Threading.Thread.Sleep(500)
    Loop
End Sub
 

cjard

Well-known member
Joined
Apr 25, 2006
Messages
7,056
Programming Experience
10+
I want to use a for/next loop to take up a predetermined length of time before a statement executes,

As you may have realised, from JohnH's code, the way to make your program pause for a determined amount of time, before carrying out an action, is to put the thread that will work on the action, to sleep for that amount of time.

System.Threading.Thread.CurrentThread.Sleep(500) will make the current thread (the thread that encounters this statement) sleep for half a second

JohnH puts his code in a loop, with a DoEvents- every .5 seconds the ui will wake up, and process all the messages. THis is one way to keep the UI responsive, but it still leads to a delay in response.

A better way is to spawn a thread that will do some work, and make that thread sleep for X milliseconds while the main thread carries on responding. In .NET 2 you can use a backgroundworker to do this. The first job your background worker should do is go to sleep for the requisite amount of time.
 

nod

Member
Joined
Nov 26, 2006
Messages
5
Programming Experience
Beginner
Interesting

I have done some research and have found various discussions on timers vs. using threads to sleep. I am interested in hearing more and it looked as if cjard was getting into it. Is there a good resource or guidance that could be given to accomplish your examples?
 

nod

Member
Joined
Nov 26, 2006
Messages
5
Programming Experience
Beginner
Multi-Threading

What I am looking for are examples of multithreading. I'm a SQL DBA but have always done some VB stuff on the side so to speak. I have read many discussions on multithreading but none seem to evolve well with VS2005. It looks as if you guys know what you are doing so...
 

cjard

Well-known member
Joined
Apr 25, 2006
Messages
7,056
Programming Experience
10+
In .NET 2.0 you would work it like this:

Create or reuse a class that represents all the data that a worker needs to process a particular request. For example, I have an app that allows me to queue hundreds of directories of mp3 for lookup on freedb. For this, the worker already knows the address of the freedb server, it just needs the path of the directory.
These work requests are put into a System.Collections.Generic.List(Of DirectoryInfo) because I make a DirectoryInfo pointing to the directory and drop it in the list.
If my BackgroundWorker object (dropped on the form from the toolbox, very simple!) is not .Busy (a property) then I tell it to start work
The BGWs job is to go to the list and look up the album. Work is implemented by filling code into a DoWork() function, so that function calls on another class to actually do the work, because I dont do huge amount of non-UI code in the user interface
When the worker is finished with one item of work, it loops round to the start, if there are more jobs. As soon as the queue is done, it finishes and the .Busy property becoems false. It would hence only be activated the next time i queue something up.

Now, the background worker works on a different thread entirely, so there is nothing stopping me, as the first part of any work to be done, running a loop that puts the worker to sleep for a minute at a time. Every time the worker wakes up, it can check to see if the time is 10pm yet.
If it is, then the DoWork function can proceed.
Now suppose in your work list you had a load of things to be backed up.. At 10pm the worker would proceed to back all the list up, and upon finishing it would stop, the thread would stop etc.
You can carry on using the UI at all times because the thread doing the UI is different to the thread doing the work, get to work the next day, add some more backup jobs and they too will get done after 10pm.


I cant help you much more because I dont really know your requirement. Suffice to say you should think of your program in two parts - the main ui that queues up work for the background worker (BGW), and the DoWork function that gets the work done. It is DoWOrk that would do the sleeping, as part of the BGW's job role is "dont start until after 10pm"
 

nod

Member
Joined
Nov 26, 2006
Messages
5
Programming Experience
Beginner
Threading

Thanks you've been very helpful! I spent sometime this weekend getting used to the idea of sync and async work. Very new for me so I will continue my explorations keeping in mind your comments.

Here's a tough one, is there any way of telling the threads or workers to only utilize xx number of cpu time? It seems that nomatter if the work is being done by a separate thread or not if the CPU is pushed to the max then what is the point. Of course in my work so far I've simple been running loops and haven't done any real world stuff but suppose I want to set the code to execute at a lower priority or consume fewer cpu usage even if it slows want it is doing. How likely is that as a possiblity?
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,609
Location
Norway
Programming Experience
10+
You can't change BackGroundWorker thread priority, for a regular thread set the .Priority property to one of the ThreadPriority values.
 

Latest posts

Top Bottom