TimerTask不以预定间隔执行

时间:2010-11-03 21:35:17

标签: blackberry timer

我正在为BlackBerry编写一个秒表应用程序(类似于BlackBerry内置的StopWatch)。有一个显示当前时间的计时器标签,格式为MM:SS:T(分钟,秒,十分之一秒)。使用TimerTask每100毫秒刷新一次标签。

应用程序运行良好且时间显示正确,但是,有些时刻定时器标签不会以预定间隔(每100毫秒)更新一次。计时器标签暂停(不计数)一段时间并继续计数(同时仍然正确显示时间)

我的想法是在暂停期间不执行TimerTask更新计时器标签。你知道为什么应用程序这样做,以及如何解决它?

以下是更新计时器标签的主题:

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();
  }
}

timerTask:

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

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

和iUpdateTimerLabel方法:

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

  synchronized(Application.getEventLock())  
  {  
    lblSpotTime.setText(sign+sMin+":"+sSec+"."+sTenth+" ");  
  }    
} 

1 个答案:

答案 0 :(得分:2)

首先是测量它...记录你的时间任务开始和结束时的时间戳,看看它是否真的是TimerTask真正的问题。有了这些,我发现的一些事情是,

  1. 你的任务是否阻塞(可能是 一些UI的事情)?
  2. 是否还有其他任务 Timer实例?我不知道它是否被指定为这样,但是任务可能都在一个线程上运行,所以如果另一个任务妨碍了,你的任务可能无法按照指定的时间间隔运行。
  3. 您的TimerTask是否与UI事件循环正确同步(即,是否使用正确的runLater()或黑莓UI提供的任何方法更新标签)?如果您不这样做,UI事件循环可能不会注意到您已更改标签。我认为在Blackberry上,正确的是invokeLater()或者invokeAndWait(),这取决于你想要实现的目标。
  4. 在代码发布后编辑

    一些有用且相关的资源是here

    1. 好的,我仍然会说要通过一些日志记录或println调用来输出你的代码 时间戳运行时。
    2. 不确定为什么schedule()调用在它自己的Runnable内...你不需要它,但也许你的应用程序是出于某种原因我无法看到它。如果你认为你正在为计时器创建一个显式线程,那你就不是。你可以创建Timer并从任何应用程序线程设置它来调用schedule()Timer包含一个将执行此工作的强制线程,并且引入Yet Another Thread可能是多余且令人困惑的。
    3. 我仍然认为你可能想做类似的事情:
    4. 另一个提醒,实际上测量计时器正在做什么而不是依赖我的推测......
    5. TimerTask

      中的代码
      public void iUpdateTimerLabel()  
      {  
      //calculate : sign, sMin, sSec, sTenth     
      
      // synchronized(Application.getEventLock())  
        UiApplication.getUiApplication().invokeLater(
          new Runnable() { 
            @Override
            public void run() {
              lblSpotTime.setText(sign+sMin+":"+sSec+"."+sTenth+" ");  
            }
          });  
      } 
      

      你的synchronized电话可能足以防止事情发生,但这并不是首选方式。如果Timer主题专用于此单一目的,则如果您愿意,可以将invokeLater()替换为invokeAndWait()

      其他人可能能够阐明仅仅持有UI锁和实际在UI线程上运行之间的区别,但我的猜测是后者强制invalidate(),而前者不强制。{{1}}。这可以解释为什么您的标签更改只会偶尔出现。