WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Functions

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

TimeDelay Discussion

Keywords: 	 timedelay discussion

Question:

I looks like the timedelay function is triggered to complete based upon the system clock. Something like this code will delay wrongly:
timedelay(30)
message("","done")
exit
If, while the delay is running, the system clock is changed backward, the delay waits until the actual time reaches 30 seconds after it starts. I set the clock back 5 minutes, and the delay took 5 min 30 seconds.

Then I set the clock ahead 5 minutes and the message appeared instantly after applying the clock change.

Is there a workaround? I have a process that has to kick off every xx minutes, even when daylight savings time switches the clock. I need to process differently based on the real time, so not doing DST is not too attractive.

Even a Timedelay(1) gets stuck for one hour if the clock gets set back an hour.

Answer:

That's how TimeDelay works. Basically a TimeDelay is converted to a TimeWait based on the current system clock.

If the clock changes, then the TimeDelay can also be affected.

A TimeDelay(30) is just a:

now=TimeYmdHms()
later=TimeAdd(now,"0000:00:00:00:00:30")
TimeWait(later)

Options are to:

a) Disable the automatic time changing, or

b) Add code to detect this might occur and do *something*. This could get interesting as different area's have different rules for changing the daylight savings time settings.

Question on Yields (cont'd):

Tried to use Display()... It seems to behave. I would have thought it would work the same? Unfortunately, I don't want the popup. How many yields are there in 1 second? (that just sounds weird) Maybe this?
For j=1 to 1000
Yield
Next
Is there a workaround? Such as TimeDelay(-30)?

Answer:

No fixed number of Yields per second.

Any solution not incorporating TimeDelay will use up *lots* of CPU time.

The TimeDelay(-30) uses the sleep API I think. However WinBatch is completely locked for that period, and it *may* affect some programs like InstallShield, making InstallShield take nearly forever to do anything.

Question (cont'd):

Here's an attempt. (One that doesn't freeze the system.)
#DefineFunction Snooze(Seconds)
User32 = DLLLoad(StrCat(DirWindows(1),"User32.DLL"))
Milleseconds = Seconds * 1000
Timeout = Milleseconds
LastTick = GetTickCount()
while(1)
x = DLLCall(User32,long:"MsgWaitForMultipleObjects",long:0, long:0, long:0, long:Timeout, long:255)
if x == 0
Yield()
Timeout = (Milleseconds - (GetTickCount() - lastTick))
If Timeout < 0 Then break
Else
break
endif
endwhile
return
#EndFunction


AddExtender("wilx34i.dll")
BoxOpen("Test","There is a test in progress.")
Time1 = GetExactTime()
Snooze(20)
time2 = GetExactTime()
BoxShut()

Message("Elapsed time", xGetElapsed(time2, time1))

Answer:

Good. But....

A few programs (Like InstallShield) send out some kind of randon query to all programs in the system. And if this query is not responded to, InstallShield will wait up to about 20 seconds for a response. And it sends *lots* of these queries.

While the code is sitting in the WaitForMultipleObjects, then WinBatch cannot respond.

However....

If you put it in a loop, and timedout every second, then you could keep the system running -- WinBatch processes system stuff in between each script statement,

And...

The Tickcount wraps every 43 days, so you have to be careful with it. However you may be able to detect that a wrap occurred and handle it.

TimeDelays are *almost* as bad as random numbers.

Question (cont'd):

>>If you put it in a loop, and timed out 
>>every second, then you could keep the
>>system running 
I think "MsgWaitForMultipleObjects" exits whenever a message arrives. (255 as the last parameter means "wait for any kind of event.") Note that the call is in a loop, and is followed by a "Yield" so the event can process. The loop breaks when the return value indicates a timeout.

Not sure how to test this with the kind of events that InstallShield causes, but I put in a display and saw it happen when a mouse event occured. (The mouse moving over the box window.)

>>The Tickcount wraps every 43 days
Shouldn't matter. All we need is the difference between the current tick count and the one we had a few milleseconds ago. When it wraps it will appear to go from a small negative to a small positive, but the difference should still come out right.

By the way... I've simplified the routine a bit. Here's the new improved version:

#DefineFunction Snooze(Seconds)
User32 = DLLLoad(StrCat(DirWindows(1),"User32.DLL"))
EndTicks = GetTickCount() + (Seconds * 1000)
while(1)
Timeout = EndTicks - GetTickCount()
if Timeout < 0 then break
if 0 != DLLCall(User32,long:"MsgWaitForMultipleObjects",long:0,long:0,long:0,long:Timeout,long:255) then break
Yield()
endwhile
DLLFree(User32)
return
#EndFunction

; ******* Test it *******

AddExtender("wilx34i.dll")
BoxOpen("Test","There is a test in progress.")
Time1 = GetExactTime()
Snooze(10)
time2 = GetExactTime()
BoxShut()
Message("Elapsed", xGetElapsed(time2, time1)) 

Answer:

Hmmm. OK the timing and looping seem OK, but I'm still worried about the wrapping.

Actually there are two wrapping points.

GetTickCOunt is a DWORD and the DWORD wraps at 43 days.

But WinBatch runs in longs, and the long version will wrap in 21.5 days, wrapping from a BIG postive to a BIG negative. And you subtract them and get ummm. I dunno. But I would worry.

Then at 43 days it does the small negative to small positive wrap.

Question (cont'd):

The wrapping will make no difference, thanks to the magic of two's compliment arithmetic.

Here's a DebugTrace that shows what I mean:

*******************************************
* Wrapping from a negative to a positive
*******************************************

Before = -25 ; Hex "FFFFFFE7"
(0) VALUE=> -25

After = Before + 100 ; 100 ticks later
(0) VALUE=> 75

Difference = After - Before
(18) VALUE=> 100


*******************************************
* Wrapping from a positive to a negative
*******************************************

Before = 2147483632 ; = Hex 7FFFFFF0
(27) VALUE=> 2147483632

After = Before + 100 ; Hex "80000054"
(27) VALUE=> -2147483564

Difference = After - Before
(27) VALUE=> 100 






Article ID:   W15505
File Created: 2003:05:13:11:28:24
Last Updated: 2003:05:13:11:28:24