Do Loops and Timers

M

MikeS

Can someone tell me why my program hangs when I call a timer function from
within a Do Loop. Here is the code:

Public Class MainForm

Public intCounter As Double = 0
Public intMin As Double
Public intSec As Double

Private Sub btnStart_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnStart.Click

If btnStart.Text = "Start" Then
btnStart.Text = "Stop"
Else
btnStart.Text = "Start"
End If

lblTimeMin.Text = "0:"
lblTimeSec.Text = "00"

'Do While intCounter < 600
Call MyTimer()
intCounter = intCounter + 1
intMin = Int(intCounter / 60)
intSec = intCounter Mod 60

lblTimeMin.Text = Convert.ToString(intMin & ":")
lblTimeSec.Text = Convert.ToString(Format(intSec, "00"))
'Loop

End Sub

Private Sub MyTimer()
Dim start, finish As Double
start = Microsoft.VisualBasic.DateAndTime.Timer
finish = start + 1
Do While Microsoft.VisualBasic.DateAndTime.Timer < finish

Loop

End Sub

Private Sub btnExit_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnExit.Click
Me.Close()
End Sub
End Class

Thanks,

Mike
 
A

Armin Zingler

MikeS said:
Can someone tell me why my program hangs when I call a timer
function from within a Do Loop.

It hangs because it is doing the loop.

You might call threading.thread.sleep in order to wait without CPU
utilization, but, what's your intention? Waiting often doesn't make sense.
Is using a Timer and responding to it's Tick event an option?


Armin
 
M

MikeS

Hello Wolf,

The timer will work without the Do Loop and the Do Loop will work without
the timer. They will NOT work together.
 
W

Wolf Saenger

Hello MikeS,
Hello Wolf,

The timer will work without the Do Loop and the Do Loop will work
without the timer. They will NOT work together.

So than you what you inside the loop?
do you set the time again?
 
C

Cor Ligthert[MVP]

Mike

Of course the answer from Armin obout using a timer is better however just
for the situation itself.
Can you try this one?

Do While start < finish
start = Microsoft.VisualBasic.DateAndTime.Timer
Cor
 
M

Michel Posseth [MCP]

Your program hangs because of the loop and because of the fact that
everything needs to be processed by the GUI thread


if you would throw in an refresh on the labels you wil see that it actually
is working
however as soon as you move the form it will freeze

this is normall behavior this is just how things work the message pump is so
bussy with processing that it can`t find the time to redraw the form

how can you bypass this problem ?

well the simplest way in my opinion is to split the worker thread from the
GUI my personal favorite to do such simple tasks is to use asynchronous
delegates

here is a modified version of your code that will work how you wanted it to

Public Class MainForm
Public intCounter As Double
Public intMin As Double
Public intSec As Double
Private mvar_WorkerRun As Boolean
Private Sub btnStart_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnstart.Click

If btnstart.Text = "Start" Then
btnstart.Text = "Stop"
mvar_WorkerRun = False
Else
btnstart.Text = "Start"
lblTimeMin.Text = "0:"
lblTimeSec.Text = "00"
mvar_WorkerRun = True
Dim AsyncVerwerken As New AsynChWiNoParameters(AddressOf
Me.Worker)
AsyncVerwerken.BeginInvoke(Nothing, Nothing)
End If
End Sub
Delegate Sub AsynChWiNoParameters()

Private Sub Worker()
Do While intCounter < 600
Call MyTimer()
intCounter = intCounter + 1
intMin = Int(intCounter / 60)
intSec = intCounter Mod 60
GUIUpdate()
If Not mvar_WorkerRun Then Exit Do
Loop
End Sub
Private Sub GUIUpdate()
If lblTimeMin.InvokeRequired Then
Dim d As New AsynChWiNoParameters(AddressOf GUIUpdate)
Me.Invoke(d, New Object() {})
Else
lblTimeMin.Text = Convert.ToString(intMin & ":")
lblTimeSec.Text = Convert.ToString(Format(intSec, "00"))
End If

End Sub
Private Sub MyTimer()
Dim start, finish As Double
start = Microsoft.VisualBasic.DateAndTime.Timer
finish = start + 1
Do While Microsoft.VisualBasic.DateAndTime.Timer < finish OrElse Not
mvar_WorkerRun

Loop
End Sub
Private Sub MainForm_FormClosing(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Me.mvar_WorkerRun = False
End Sub
End Class


HTH

Michel
 
C

Cor Ligthert[MVP]

Ad.

For those who not understand Dutch

AsyncVerwerken

Can be by instance translated as

AsyncProcess
or
AsyncRun
or
AsyncPerform

Cor
 
C

Cor Ligthert[MVP]

For those who not understand Dutch

AsyncVerwerken

Can be by instance translated as

AsyncProcess
or
AsyncRun
or
AsyncPerform

I should have added my friendly smile while writing this.

Nice help of course from Michel

:)

Cor
 
M

Michel Posseth [MCP]

AsyncVerwerken

Normally i do all my coding in English ,,, funny that this slipped in

and for this
I should have added my friendly smile while writing this.

i would never doubt on your intentions , i know you well enough ;--)

michel
 
M

MikeS

Thanks to all for your input. That works really good. One thing I noticed
though, is if you stop and restart the timer, it starts doing double time.
 
M

Michel Posseth [MCP]

Thanks to all for your input. That works really good. One thing I
noticed
though, is if you stop and restart the timer, it starts doing double time.


this would solve your problem
Private Sub Worker()
intMin =0: intSec =0

However what would happen if your worker loop finishes its 600 iterations ??
so in advance bugfix 2

btnstart.Text = "Stop"
mvar_WorkerRun = False
End Sub

so the whole Worker sub becomes

Private Sub Worker()
intMin =0: intSec =0
Do While intCounter < 600
Call MyTimer()
intCounter = intCounter + 1
intMin = Int(intCounter / 60)
intSec = intCounter Mod 60
GUIUpdate()
If Not mvar_WorkerRun Then Exit Do
Loop
btnstart.Text = "Stop"
mvar_WorkerRun = False
End Sub


HTH

Michel
 
M

MikeS

Michel,

I tried that but it didn't resolve the double time issue. Just to give you
an idea, imagine the timing of this sequence:

---1---2---3---4---5---6---7---8 the first time and after stopping and
restarting

--12--34--56--78 and so on.

Hope this makes sense.

Thanks,

Mike
 
M

Michel Posseth [MCP]

AHA

i see what you mean


This version wil also not hog up the CPU


Public Class MainForm

Public intCounter As Double

Public intMin As Double

Public intSec As Double

Private mvar_WorkerRun As Boolean

Private Sub btnStart_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles btnstart.Click

mvar_WorkerRun = Not mvar_WorkerRun

If mvar_WorkerRun Then

btnstart.Text = "Stop"

lbltimemin.Text = "0:"

lbltimesec.Text = "00"

Dim AsyncVerwerken As New AsynChWiNoParameters(AddressOf Me.Worker)

AsyncVerwerken.BeginInvoke(Nothing, Nothing)

Else

btnstart.Text = "Start"

End If

End Sub

Delegate Sub AsynChWiNoParameters()

Private Sub Worker()

intCounter = 0

Do While intCounter < 600

Call MyTimer()

intCounter = intCounter + 1

intMin = Int(intCounter / 60)

intSec = intCounter Mod 60

GUIUpdate()

If mvar_WorkerRun Then

Application.DoEvents()

Else

Exit Do

End If

Loop

End Sub

Private Sub GUIUpdate()

If lblTimeMin.InvokeRequired Then

Dim d As New AsynChWiNoParameters(AddressOf GUIUpdate)

Me.Invoke(d, New Object() {})

Else

lblTimeMin.Text = Convert.ToString(intMin & ":")

lblTimeSec.Text = Convert.ToString(Format(intSec, "00"))

End If

End Sub

Private Sub MyTimer()

Dim start, finish As Double

start = Microsoft.VisualBasic.DateAndTime.Timer

finish = start + 1

Do While Microsoft.VisualBasic.DateAndTime.Timer < finish

If mvar_WorkerRun Then

Application.DoEvents()

Else

Exit Do

End If

Loop

End Sub

Private Sub MainForm_FormClosing(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

Me.mvar_WorkerRun = False

End Sub

End Class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top