Home > Flex > Don’t Let Your Timers Creep!

Don’t Let Your Timers Creep!

August 22nd, 2008

It’s been a while since I’ve done a pure programming post, so here we go. A co-worker just dropped by to ask whether I would expect timers in ActionScript 3.0 to be accurate. I said, “why yes, of course!” But there’s a wrinkle: if you set a Timer to go off indefinitely (i.e., with a repeatCount of 0), it appears that the timer doesn’t start the next interval until the listener function returns. So if you don’t correct for this, then your timer function will creep by the duration of the listener function. If your listener function does something that’s potentially lengthy, you might want to execute it with a callLater() so that the timer isn’t affected. But the timer will still creep unless you apply a correction. Here’s some sample code that demonstrates the effect, side-by-side with a correction.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="{onCreationComplete(event)}">
	<mx:Script>
		<![CDATA[
			import mx.utils.StringUtil;
			import mx.events.FlexEvent;
			private const BASE_INTERVAL:Number = 1000;
			private var _creepingTimer:Timer = new Timer(BASE_INTERVAL);
			private var _steadyTimer:Timer = new Timer(BASE_INTERVAL);
			private var _startTime:Date;
 
			private function onCreationComplete(e:FlexEvent) : void
			{
				_creepingTimer.addEventListener(TimerEvent.TIMER, onCreepingTimer);
				_creepingTimer.start();
				_steadyTimer.addEventListener(TimerEvent.TIMER, onSteadyTimer);
				_steadyTimer.start();
				_startTime = new Date();
			}
 
			private function onCreepingTimer(e:TimerEvent) : void
			{
				var now:Date = new Date();
				var deltaMS:int = now.time - _startTime.time;
				uiCreepingLog.text += StringUtil.substitute("\r{0}", deltaMS); 
			}
 
			private function onSteadyTimer(e:TimerEvent) : void
			{
				var now:Date = new Date();
				var deltaMS:int = now.time - _startTime.time;
				uiSteadyLog.text += StringUtil.substitute("\r{0}", deltaMS);
				var offset:int = deltaMS % BASE_INTERVAL;
				_steadyTimer.delay = offset < 500 ? BASE_INTERVAL - offset : BASE_INTERVAL;
			}
 
 
		]]>
	</mx:Script>
	<mx:HBox width="100%" height="100%">
		<mx:TextArea id="uiCreepingLog" width="50%" height="100%" text="Creeping timer:"/>
		<mx:TextArea id="uiSteadyLog" width="50%" height="100%" text="Steady timer:"/>
	</mx:HBox>
</mx:Application>

id="CreepingTimer" width="100%" height="100%"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> width="100%" height="100%" name="CreepingTimer" align="middle"
play="true"
loop="false"
quality="high"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
Author: David Coletta Categories: Flex Tags:
  1. August 22nd, 2008 at 16:38 | #1

    Inspired programming, Very useful info for new users of AS like me.

  2. October 14th, 2008 at 10:10 | #2

    Hi David, great discovery and workaround!
    However, I can’t seem figure to figure out why you do this:
    _steadyTimer.delay = offset < 500 ? BASE_INTERVAL – offset : BASE_INTERVAL;

    and not simply

    _steadyTimer.delay = BASE_INTERVAL – offset;

    What’s the reason for checking if offset is smaller than 500?

  3. January 19th, 2009 at 14:19 | #3

    Just wanted to say thank you very very much for this. I was dealing with a lagging timer and it wasn’t apparent that this was the cause. Thanks for the enlightenment and workaround.

  4. May 31st, 2009 at 10:49 | #4

    Thank you! I’d been struggling with this problem for weeks, and thanks to your post I managed to fix it one day before the deadline :D

  1. August 27th, 2008 at 11:39 | #1
  2. September 9th, 2008 at 11:59 | #2
  3. October 14th, 2008 at 12:35 | #3
  4. February 18th, 2010 at 07:08 | #4