Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Contributor
tuyennguyencanada
Posts: 41
Registered: ‎07-28-2010
My Device: Not Specified

TimerTask does not execute at predetermined interval

I'm writing a stopwatch application for BlackBerry

(which is similar to the BlackBerry built-in StopWatch).

 

There is a timer label displaying current time in the format MM:smileyfrustrated:S:T (minutes, seconds, tenth of second).

 

The label is refresh each 100 millisecond with TimerTask.

 

The application works well and the time is display correctly, however, there are some moments the timer label is not updated at the predetermined interval (each 100 milliseconds).

 

The timer label pauses (not counting) for a while and continues counting (while still displays the time correctly)

 

My thought is the TimerTask is not executed to update the timer label during this pause.

 

Do you know why the app act this way, and how to fix it?

Below are the Thread to update the timer label:

public class ThreadUpdateTime extends Thread  
{  
 
private MyMainScreen myMainScreen;  
 
private Timer updateTimerLabelTimer = new Timer();

 
public ThreadUpdateTime(MyMainScreen parent)
 
{
    myMainScreen
=parent;
 
}

 
public void run()
 
{
   
try {
      updateTimerLabelTimer
.schedule(new RecordTimer(myMainScreen), TIMER_DELAY, TIMER_INTERVAL);

   
} catch (Exception e)  {
     
//put alert here
   
}
 
}

 
public void iStop()
 
{
    updateTimerLabelTimer
.cancel();
 
}
}

the timerTask:

public class RecordTimer extends TimerTask  
{  
 
private MyMainScreen myMainScreen;  
 
public RecordTimer(MyMainScreen parent)  
 
{  
    myMainScreen
=parent;  
 
}  

 
public void run()  
 
{  
    myMainScreen
.iUpdateTimerLabel();  
 
}  
}  

and the iUpdateTimerLabel method:

public void iUpdateTimerLabel()  
{  
//calculate : sign, sMin, sSec, sTenth    

 
synchronized(Application.getEventLock())  
 
{  
    lblSpotTime
.setText(sign+sMin+":"+sSec+"."+sTenth+" ");  
 
}    
}
Developer
mreed
Posts: 1,041
Registered: ‎07-16-2008
My Device: ಠ_ಠ

Re: TimerTask does not execute at predetermined interval

[ Edited ]

Calling setText() on your LabelField too often is bad for performance and will lag your app because it calls updateLayout(). Try drawing the text manually and just calling invalidate() to repaint your custom Field. If you are already painting manually, then you shouldn't need to sync with event lock.

 

Also, you may want to schedule the task to run at a fixed rate so if it does lag then it won't try to play catch.

Developer
arkadyz
Posts: 2,268
Registered: ‎07-08-2009
My Device: various

Re: TimerTask does not execute at predetermined interval

One of the approaches: check your scheduledExecutionTime() on each run() and just return if you are more than, say, half of your TIMER_INTERVAL behind.

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Contributor
tuyennguyencanada
Posts: 41
Registered: ‎07-28-2010
My Device: Not Specified

Re: TimerTask does not execute at predetermined interval

Thanks mreed and arkadyz, I'll try each of your suggestions and report back to you guys.

 

 

Developer
amrishodiq
Posts: 112
Registered: ‎09-23-2009
My Device: Not Specified

Re: TimerTask does not execute at predetermined interval

You should use 

 

updateTimerLabelTimer.scheduleAtFixedRate(something and something);

instead of schedule()

Developer
LSphone
Posts: 140
Registered: ‎02-08-2010
My Device: Torch 9800, Storm 9530, Curve 8330

Re: TimerTask does not execute at predetermined interval

[ Edited ]

Maybe this would help:

 

 

TimerTask TT;
(new Timer()).scheduleAtFixedRate(TT = new TimerTask() {
    boolean first=false;
    long lastime=System.currentTimeMillis();

    public void run() {
      if (first) {
        first = false;
        try {
          Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
          } catch (Exception e) { }
        }
      /* When it backs up and then races to catch up,
         don't redraw display so much that it might cause
         more lag, but also don't be so stingy that it
         causes significant lag by omission. */
      long currtime = System.currentTimeMillis(); if ((currtime - lastime) < 0.05) label.setText( displayString(currtime) ); lastime = currtime; } } , 100, 100);

 

The point about setText being slower than drawing the text yourself is interesting, but for a mere 10 frames per second it should be no problem if you're doing little or nothing else.

 

Also, as amrishodiq points out, for this you'll want to use scheduleAtFixedRate instead of schedule().  The difference is, when the phone is interrupted by something higher-priority as inevitably happens, and there is a lag so that one or more calls to the timer are backed up, schedule() will resume triggering the timer at the proper rate, but drop the triggers that were missed.  As long as the timer is reading the absolute time every time instead of incrementing a counter, that won't cause any cumulative error, but it will cause the display updating to skew freely by up to a tenth relative to when the actual time increments by a tenth.  That's because after a lag, the TimerTask resumes triggering approximately every tenth, but not at the same delta-t to when the system time counts up a tenth.  Basically it would be like a timer that's loosely frequency-locked with the system time, but is not phase-locked (thinking of the system time modulo the period as a sawtooth wave).  So the counter would appear to count unevenly, like the second hand of the Windows clock ticks unevenly but the clock doesn't suffer any cumulative error in minutes.

 

By contrast, scheduleAtFixedRate will race to catch up when your thread can get priority again, so the counter would rip through a few counts (which the user wouldn't notice because they'd all display the correct current countdown time) and then be back on the intended rate, loosely phase-locked as well as loosely frequency-locked with the system time.  The counting would then appear more even.

 

See what I mean?  Either way you are going to see the counter hesitate when the phone is busy with something else, you can't take precedence over everything even when requesting high priority.  But if you use schedule(), it will look more sloppy, whereas with scheduleAtFixedRate() it should look more solid.

 

Contributor
tuyennguyencanada
Posts: 41
Registered: ‎07-28-2010
My Device: Not Specified

Re: TimerTask does not execute at predetermined interval

There must be something else I'm missing. This is the complete source code of the app:tuyennguyen.ca/data/blackberry/stopwatch/StopWatch.zip The project is developed with BlackBerry JDE Eclipse Plugin, JRE 5.0.0, simulator BlackBerry Storm. Hope anyone could see where the problem is.