Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I was Shocked 1

Status
Not open for further replies.

yacyac

Programmer
Jul 29, 2002
78
US
I was playing around with comparing
Private Declare Function GetTickCount Lib "kernel32" () As Long

to the Timer in VB.

The CPU usage for the API call was about 50% and the CPU usage for the VB Timer was basically nothing. The code I was using is below. I don't know why but I always assumed API calls were more efficient. Did I do something wrong? All of my VB6 knowledge has been self taught. The only formal program classes I have had were in Fortran and GW Basic - many - many moons ago.

Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Sub Command1_Click()
Dim t1 As Long
Dim t2 As Long
Dim Countit As Long

''Make Sure timer is OFF
Timer1.Enabled = False

'Hide visual indicators
Shape1.Visible = False
Shape2.Visible = False

''If no value or negative value in text1 get out
If Val(Text1.Text) < 1 Then
Shape1.Visible = True
Shape2.Visible = True
MsgBox "Booboo"
Exit Sub
End If

''Get milliseconds to count
Countit = Val(Text1.Text)

''Set Timer
Timer1.Interval = Countit


'set Tickcount
t1 = GetTickCount

''Start Timers
If chkTimer.Value = 1 Then Timer1.Enabled = True

If chkTicker.Value = 0 Then Exit Sub
Do
''Keep keyboard, mouse and screen from freezing
DoEvents

t2 = GetTickCount

Loop Until t2 - t1 = Countit
Shape1.Visible = True



End Sub

Private Sub Form_Load()

End Sub

Private Sub Text1_DblClick()
''Clear Textbox
Text1.Text = ""
End Sub

Private Sub Timer1_Timer()
Shape2.Visible = True
Timer1.Enabled = False
End Sub
 
Well, without being specific, I will point out that API calls can only ever be as efficient as the code that the API implements. Inefficient code is inneficient.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
>Am I doing something wrong

A tight loop in a single threaded application ...
To demonstrate it isn't the API call at fault, let's add another API call into the loop and watch the CPU time go down

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

The add Sleep 50 after DoEvents. Oh, and you might want to change

Loop Until t2 - t1 = Countit

to

Loop Until t2 - t1 >= Countit
 
Thanks Strongm. I was planning on the >= Countit. I will play with the Sleep this weekend.
 
Ah but with Sleep, what if you want something else to be able to happen like a keystroke while the sleep is in process?

Sleep seems to suspend everything and it looks like it is the doevents in the other methods that is using up the CPU.

My tests showed gettickcount was about the same as timer.(50% of one of my cores)

Is there any alternative to the old timer control to give an independent time delay?
 
That's why the Sleep is set to 50ms, to retain application responsiveness. Did you try the example with my changes?

>it is the doevents in the other methods that is using up the CPU

Why not try removing the DoEvents from both the initial example and the updated version to see what happens?

>Is there any alternative to the old timer control to give an independent time delay?

Yes, there are alternatives. But they tend to involve API callbacks.
 
The problem I see here is that you haven't stated what problem you're trying to solve. Instead we're presented with a question about two ways to implement a "solution" you've grasped at - using different timer techniques.


Every time I see somebody fiddling with DoEvents() calls I get suspicious. Most often they seem to be fighting the VB Form paradigm.

In a VB Form you are not in control. The form is running a message loop, and that loop makes calls into your "event handler" routines. Trying to seize control as if you're running the show almost always leads to convoluted code that won't always produce consistent results.

The big offender here is writing "straight line" processing logic. The sort of logic that assumes you can just stay in some tight loop forever (until some workload is complete). This is a problem because you've lost sight of the fact that all of your Form code consists of "soft interrupt" handlers. The main thread of execution belongs to the Form, not your event handlers.

DoEvents() calls are a sort of escape valve to allow lengthy interrupt processing to occur. They bring risks of their own though, beginning with unanticipated re-entrancy.


In VB5/6 there are really only about three ways to handle these situations, which truly do occur in real programs:
[ul][li]Fiddle and twiddle with DoEvents(), Sleep(), Timer()/GetTickCount(), etc.[/li]
[li]"Quantify" and state-manage your long running workload then drive it via something like a Timer control. I.e. decompose a "1 million times" loop into a "1000 times" loop that gets run when the Timer triggers. Use someting like a 10ms. Timer and turn it off at the head of the event handler and back on at the bottom. Tune this "inner loop" and Timer.Interval for performance/responsiveness as required.[/li]
[li]Delegate the long running workload to a non-interactive "formless" process that can asynchronously notify you upon completion. In other environments you might use a thread, but in VB6 using a process ends up being a lot safer and less hassle.[/li][/ul]
The latter option works pretty well actually. You can easily sync using TCP/IP, Named Pipes or Mailslots, or StdIO redirected through Anonymous Pipes. You could also get trickier and use an ActiveX EXE as the "slave" worker process - though this requires some fiddling too.

The bonus? Architecting your application in this manner leads to much clearer, cleaner, and more maintainble code. Such a secondary "worker" process can even accept multiple different workload requests (with parameters) fairly simply: you just send it "do this" messages via the IPC mechanism you implemented.
 
Very good.
I have often marvelled how you can have data being received via a winsock and comms control while at the same time be showing a movie without interruption and have a timercontrol ticking away each second to show the time of day,(Like in a public information display application or info kiosk).

Right at the heart of all these devices there must still be a clock tick happening regularly that is counted down millions of times to produce the result.
Is the source of the time the actual microprocessor clock or do the current PC chips have a separate hardware timer like in some microprocessors?

I usually try to have only ONE VB6 timer control and count off a variable if I need longer intervals rather than have multiple timer controls for things like flashing banners.
 
>Is the source of the time

You asked this about a year ago, and I answered it at that time.
 
I played around with Sleep() and DoEvents this weekend. As usual, strongm is correct, if I envoke Sleep(50) after the DoEvents, the CPU usage is the same as using a Timer (near nothing), and there is no noticable freeze. Thanks again strongm. My use is related to music and timers. The timers usually use minutes:seconds:frames, where there are 72 frames in a second or 13.88 milliseconds per frame. Since there are 4 different players, rthere are a minimumn of 4 timers and typically more. So I was just looking to see what would use the least amount of CPU. From the simple test above with strongm's help, it appears not to matter as long as I include DoEvents and Sleep. In my case I will need to look at reducing the length of the Sleep.

Without the DoEvents, the keyboard and mouse are frozen.
Dilettante, thanks for your input, I will look at attempting to use fewer timers and additional variables.

Thanks to all for your help.
 
>Is the source of the time the actual microprocessor clock or do the current PC chips have a separate hardware timer like in some microprocessors?

Sorry I don't ever remember seeing your answer to this question.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top