QB64.org Forum
Active Forums => QB64 Discussion => Topic started by: hanness on April 20, 2021, 10:36:44 am
-
In the following code sample, I have a DO...LOOP that simply prints out how many seconds have elapsed once per second.
Before that loop is started, I seup a timer to run a subroutine every 5 seconds. That subroutine simply prints out how many times it has been run.
What's odd is that the first timer event does not happen after 5 seconds, it happens after 10 seconds. After the first run it correctly runs every 5 seconds.
If you change the interval, the same thing still happens. For example, if I set the timer to 10 seconds, the first execution of the timed event happens after 20 seconds, not 10 seconds.
Is this expected behavior for some reason?
Test scenario: QB 1.51 (April 9, 2021 Dev Build) on Win 10 20H2
Sample code:
x = 0
y = 0
t1 = _FreeTimer
On Timer(t1, 5) GoSub DoTimedStuff
Timer(t1) On
Do
_Limit 1
x = x + 1
Print "Seconds elapsed:"; x
Loop
DoTimedStuff:
y = y + 1
Print "Timer ticks:"; y
Return
-
There must be some internal clock for QB64 cause if you add a _DELAY, even before you turn the timer on, it changes when the first run is. Also TIMERs and _LIMIT\_DELAY don't seem to like each other very much, if the TIMER value lands on a _LIMIT or _DELAY value it seems to be 50\50 who goes first.
x = 0
y = 0
x = x + 1
PRINT "Seconds elapsed:"; x
y = y + 1
-
@hanness This is probably a deep bug in the ON TIMER statement, because it works just as badly with the ON TIMER (5) statement - the old Qbasic way. I tested it in versions 1.5, 1.1 and 0.954, in all it works badly, as you say.
-
Here it works as expected, since the timer activation happens after the program had time to initialise:
Print "Seconds elapsed:";
Print "TIMER IS ON - press ENTER to toggle" Print "TIMER IS OFF - press ENTER to toggle" timeron = 1
y = 0
timeron = 0
DoTimedStuff:
y = y + 1
We're probably looking at some sort of race condition that's happening at startup - that's when the TIMER thread is created.
-
We're probably looking at some sort of race condition that's happening at startup - that's when the TIMER thread is created.
Thats why I added the _DELAY to try and let everything get setup before beginning. Whether the delay was before everything or after the timer declare it still behaved the same.
Whether the timer is 5sec or 2sec it still takes that long before it starts registering.
Probably why I have never noticed this before, most of my timers are fractions of a second. .125, .25 ect. But sure enough it always misses that first run.
So yeah if you have a ridiculous timer cycle rate like 300 seconds you literally have to wait 600 seconds before the first event happens. or wait 300 before turning the timer on.
-
Found the same problem but this ON TIMER stuff seems to be clunky. The code seems to initialize BEFORE runtime. During runtime an ON TIMER statement is ignored.
Here is some code that works with TIMER
x = 0
y = 0
y = y + 1
x = x + 1
PRINT "Seconds elapsed:"; x
Man! talk about a dangerous statement - ON TIMER. It has total disregard to LOOPS. When activated it takes priority over any other code. We are talking about WW3.
If anyone thought that my programming in common memory with assembler was nuts then this takes the cake.
-
Man! talk about a dangerous statement - ON TIMER. It has total disregard to LOOPS. When activated it takes priority over any other code. We are talking about WW3.
that is kind of the point, ON TIMER is an EVENT like an interrupt. So say you have a game where you need a message to popup every X ticks until the player completes a task regardless what else is happening in the game. Then you use ON TIMER.
-
I use it in one of my projects as a auto save for crash recovery. Of course, it doesn't really need to catch the first interval as not much of consequence would happen in that time, so I never noticed that glitch.
It saves the state every 60 seconds to an auto save directory. It uses the same SUB as a manual file save, I just send a boolean byte with the sub call that tells the sub whether to do the dialogs or save to "auto" behind the scenes. I coded it to turn the timer off before doing a manual 'named scenario' save, and then back on again after that is done. I don't know if that would be a problem, but reasoned that it shouldn't be calling the same SUB simultaneously.
I suppose it could go off in the middle of an update loop and screw up the autosave data, but then it should catch it a minute later. I figure the chance of a bad save AND a crash within 60 seconds is fairly low. It's just a case of how unlucky one is, I suppose.
-
Man! talk about a dangerous statement - ON TIMER. It has total disregard to LOOPS. When activated it takes priority over any other code. We are talking about WW3.
If anyone thought that my programming in common memory with assembler was nuts then this takes the cake.
LOL
Power tools are scary ;-))
You can turn it on and off like any good tool.
-
Thanks for the all the responses. It's not affecting anything critical for me, I simply wanted to see if I was missing something obvious here :-)
-
Yeah I can't quite figure out why it is skipping the first run of the timer. Interesting. Now it shall nag the back of my mind forever.
-
Yeah I can't quite figure out why it is skipping the first run of the timer. Interesting. Now it shall nag the back of my mind forever.
I get that! Sometimes small things that really don't matter in the grand scheme of things end up occupying way too many cycles of the underpowered central processing unit in my skull.