I have a user-triggered function that works really fast, and I want to insert a 1 second pause between when they click the button, and when the resulting action happens. I’m going to add a progress bar to it later, but first I’m just trying to insert that pause. Seems simple enough but I’m running into a problem and can’t seem to figure out what’s causing it. Here’s my code:
// remainder of function code...
Problem is, the program gets stuck in the while loop. I did some tests, and for some reason, that timerCallback is not being called while that while loop is running. If I get rid of the while loop, it runs, but it does so at the same time as the function code, thus negating the pause.
Is my logic and code correct? Or am I completely misunderstanding how this works?
If you’re calling functionThatNeedsPause on the message thread then the following information from the Timer documentation explains the behaviour:
A Timer’s timerCallback() method will be repeatedly called at a given interval. When you create a Timer object, it will do nothing until the startTimer() method is called, which will cause the message thread to start making callbacks at the specified interval, until stopTimer() is called or the object is deleted.
The time interval isn’t guaranteed to be precise to any more than maybe 10-20ms, and the intervals may end up being much longer than requested if the system is busy. Because the callbacks are made by the main message thread, anything that blocks the message queue for a period of time will also prevent any timers from running until it can carry on.[/quote]
Yeah, you’re misunderstanding good and proper!
When you request that the timer starts, some stuff happens behind the scenes which ultimately results in the message thread triggering a notification ‘when the time comes’.
If your function happens to have been called from the message thread (which is most likely, unless you have explicitly made your own thread), no other messages will ever be sent until at least that function has finished. If you’re in a while loop, waiting for a message (even indirectly), you will be there forever.
The simple solution is to break the function down into parts; when you’ve started the timer, consider the job done for the moment; timerCallback will be called when the time has elapsed - at which point you can call a function to carry out the next part of the operation.
[of course, you should bear in mind that - should the user click the button again whilst the timer is running, it will restart the timer; the ‘first part’ (the stuff you do before leaving it up to the timer callback) will be executed again, but the second part (triggered by the timer callback) would only be called once! You might therefore want to disable your button (or response to it) if the timer is running]
That clears that up. Thanks guys!
If you just need a pause, the timer seems overkill anyway. Just use
usleep(#OfMilliSeconds) (or Sleep on Windows, I guess).
NO!!! That’s terrible advice to give to a beginner!
For starters, you’d use the platform independent call Thread::sleep()!
And most importantly, sleeping AT ALL in the main event thread is a cardinal sin! (In fact, maybe I should even add an assertion to catch it if anyone attempts that…?)
And sleeping, even in background threads, is generally a sign of bad design or a desperate hack. If your thread is waiting for something, you should use a WaitableEvent if possible, which will wake up immediately when the event occurs. Looking through my code, all the places where I’ve used sleep() tend to be places where I’ve had to wait for something like an operating system function to complete, where there’s no alternative to just polling it repeatedly. But even in these places you should NEVER sleep for more than a few milliseconds without checking your thread’s status, because you never know whether something may be trying to kill it.