Page 1 of 2
how do you create a timer?
Posted: Thu May 25, 2006 8:37 pm
by josku_x
hello!
I need help to wait for some time and to continue a function.
I simply want to do this:
Code: Select all
If WaitServer
Wait 100 Milliseconds
MessageRequester("Continue", "Program will continue...")
WaitServer=0
EndIf
The problem is, I have many gadgets that need to be refreshed to show new data, and if I use Delay() or ElapsedMilliseocnds(), everything gets reezed until the wait-time is finished. So, how do I achieve this? I want that a function waits for the specified time without disturbing other stuff.
Thanks!
If this isn't clear, please let me know
Posted: Thu May 25, 2006 8:44 pm
by srod
I sometimes use something like:
Code: Select all
If WaitServer
for i = 0 to 100
delay(1)
WindowEvent() ;This allows gadgets to be refreshed etc.
next
MessageRequester("Continue", "Program will continue...")
WaitServer=0
EndIf
Alternatively, perhaps use a thread, or a Windows timer is very easy to set up.
Posted: Thu May 25, 2006 8:51 pm
by josku_x
That trick with the windowEvent() looks pretty cool!
Thanks srod!
Posted: Thu May 25, 2006 8:55 pm
by srod
Of course, you will not get an exact time of delay with this method. Mind you, the same is true with a Window's timer as that depends very much upon an application's use of the message queue etc.

Posted: Thu May 25, 2006 8:58 pm
by josku_x
OK. I was thinking of a BitTorrent client and a time delay before reconnecting is a standard feature every BT client needs to have.
Posted: Thu May 25, 2006 9:54 pm
by Kale
srod wrote:I sometimes use something like:
Code: Select all
If WaitServer
for i = 0 to 100
delay(1)
WindowEvent() ;This allows gadgets to be refreshed etc.
next
MessageRequester("Continue", "Program will continue...")
WaitServer=0
EndIf
Alternatively, perhaps use a thread, or a Windows timer is very easy to set up.
This is really not the way to do it. :p
Here is an example of a repeating call to a procedure:
Code: Select all
Procedure Echo(Text.s)
Debug Text
EndProcedure
RepeatTime.l = 1000
StartTime.l = ElapsedMilliseconds()
Repeat
If ElapsedMilliseconds() > StartTime + RepeatTime
Echo("I am being repeated every second")
StartTime.l = ElapsedMilliseconds()
EndIf
Delay(1)
ForEver
And here is how to wait for a bit without halting the event queue:
Code: Select all
;]=============================================================================
;-CONSTANTS
;[=============================================================================
#APP_NAME = "Timer Test"
Enumeration
#WINDOW_ROOT
#BUTTON_DELAY
EndEnumeration
;]=============================================================================
;-GLOBAL FLAGS / VARIABLES / STRUCTURES / ARRAYS
;[=============================================================================
Global StartTimer.b = #False
Global StartTime.l
Global DelayTime.l = 5000
;]=============================================================================
;-PROCEDURES
;[=============================================================================
;Handle an error
Procedure HandleError(Result.l, Text.s)
If Result = 0
MessageRequester("Error", Text, #PB_MessageRequester_Ok)
End
EndIf
EndProcedure
;]=============================================================================
;-GEOMETRY
;[=============================================================================
HandleError(OpenWindow(#WINDOW_ROOT, 0, 0, 120, 120, #APP_NAME, #PB_Window_SystemMenu | #PB_Window_ScreenCentered), "Main window could not be created.")
HandleError(CreateGadgetList(WindowID(#WINDOW_ROOT)), "Gadget list for the main window could not be created.")
ButtonGadget(#BUTTON_DELAY, 10, 10, 100, 90, "Press Me")
;]=============================================================================
;-MAIN LOOP
;[=============================================================================
Repeat
EventID.l = WindowEvent()
If EventID
Select EventID
Case #PB_Event_Gadget
Select EventGadget()
Case #BUTTON_DELAY
Debug "Waiting for 5 seconds"
StartTime.l = ElapsedMilliseconds()
StartTimer.b = #True
EndSelect
EndSelect
Else
Delay(1)
EndIf
If ElapsedMilliseconds() > StartTime + DelayTime And StartTimer = #True
Debug "Five seconds has elapsed!"
StartTimer.b = #False
EndIf
Until EventID = #PB_Event_CloseWindow
End
;]=============================================================================
;-END
;==============================================================================
Posted: Thu May 25, 2006 10:10 pm
by srod
Yes, I was just giving the general idea of how to refresh gadgets whilst forcing a delay. I take your point though; use of the ElapsedMilliseconds() command is a good idea.
Posted: Fri May 26, 2006 6:42 am
by josku_x
Thanks Kale, works perfectly!
Posted: Fri May 26, 2006 8:34 am
by inc.
... everything gets reezed until the wait-time is finished. So, how do I achieve this? I want that a function waits for the specified time without disturbing other stuff....
Code: Select all
Repeat
If ElapsedMilliseconds() > StartTime + RepeatTime
Echo("I am being repeated every second")
StartTime.l = ElapsedMilliseconds()
EndIf
Delay(1)
ForEver
This makes the appl. itself wait till the loop finished if its not performed in a thread and as I understood right he wants the timer to be processed in Backgr. so his gadgets ca be refreshed fast etc.
In case of a timer best would be a callback approach like included in the winAPI:
http://msdn.microsoft.com/library/defau ... tevent.asp
This is a multimediatimer (others are available also) and could easely used also for other stuff.
I do use it for proper FPS playback of moviecontend where frames are received via the avifil32 functions.
Just set the delay in ms, the timerProc callback wich calls your intervalled routine and let it go.
I do prefer the one above over the common one:
http://msdn.microsoft.com/library/defau ... ttimer.asp
In PB:
http://www.purebasic.fr/english/viewtop ... t=settimer
Cause this SetTimer() routine does interrupt when dragging the title bar of the window.
Posted: Fri May 26, 2006 12:21 pm
by Kale
inc. wrote:
Code: Select all
Repeat
If ElapsedMilliseconds() > StartTime + RepeatTime
Echo("I am being repeated every second")
StartTime.l = ElapsedMilliseconds()
EndIf
Delay(1)
ForEver
This makes the appl. itself wait till the loop finished if its not performed in a thread
The loop here is for demonstration only purposes, if you need to use this example put this code:
Code: Select all
If ElapsedMilliseconds() > StartTime + RepeatTime
Echo("I am being repeated every second")
StartTime.l = ElapsedMilliseconds()
EndIf
in your main loop. It doesn't interfere with anything.
inc. wrote:..as I understood right he wants the timer to be processed in Backgr. so his gadgets ca be refreshed fast etc.
Which is what i've demonstrated in the other code snippet. There is no need for API usage for this simple task.
Posted: Fri May 26, 2006 12:52 pm
by thefool
If you want a timer wich doesn't interfer with your main code, and is easy to use you can use a thread..!
Code: Select all
Global #timerquit
Procedure Timer1(time) ;time is in milliseconds
Delay(time)
Repeat
;YOUR REPEATED CODE
Until #timerquit=1
EndProcedure
;fire the timer every second:
CreateThread(@timer1(),1000)
Posted: Fri May 26, 2006 1:24 pm
by inc.
in your main loop. It doesn't interfere with anything.
missed that one ... sorry
Posted: Fri May 26, 2006 1:31 pm
by josku_x
thefool wrote:If you want a timer wich doesn't interfer with your main code, and is easy to use you can use a thread..!
Code: Select all
Global #timerquit
Procedure Timer1(time) ;time is in milliseconds
Delay(time)
Repeat
;YOUR REPEATED CODE
Until #timerquit=1
EndProcedure
;fire the timer every second:
CreateThread(@timer1(),1000)
Thanks thefool! I knew that I have to do a thread, but if I remember right, last week I tried it but failed. Thanks for the working example!
Posted: Fri May 26, 2006 4:32 pm
by Psychophanta
josku_x wrote:thefool wrote:If you want a timer wich doesn't interfer with your main code, and is easy to use you can use a thread..!
Code: Select all
Global #timerquit
Procedure Timer1(time) ;time is in milliseconds
Delay(time)
Repeat
;YOUR REPEATED CODE
Until #timerquit=1
EndProcedure
;fire the timer every second:
CreateThread(@timer1(),1000)
Thanks thefool! I knew that I have to do a thread, but if I remember right, last week I tried it but failed. Thanks for the working example!
Working example? are you joking or didn't even tried it? it doesn't work!

And you are not forced to create a thread.
Don't you like this?
http://www.purebasic.fr/english/viewtopic.php?t=17594
Posted: Fri May 26, 2006 4:41 pm
by srod
You'll need to use the debugger to kill the following:
Code: Select all
Global timerquit
Procedure Timer1(time) ;time is in milliseconds
Repeat
Delay(time)
Debug 1
Until timerquit=1
EndProcedure
;fire the timer every second:
CreateThread(@timer1(),1000)
Repeat
ForEver