【问题标题】:TimerTask does not execute at predetermined intervalTimerTask 未按预定时间间隔执行
【发布时间】:2010-11-03 21:35:16
【问题描述】:

我正在为 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();
  }
}

定时器任务:

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+" ");  
  }    
} 

【问题讨论】:

标签: blackberry timer


【解决方案1】:

首先是测量它...记录您的 timertask 开始和结束时的时间戳,看看它是否真的是 TimerTask 这真的是问题所在。有了这个,我想到了几件事,

  1. 您的任务是否被阻止(可能在 一些 UI 的东西)?
  2. 是否有其他任务在同一个 Timer 实例?我不知道它是否是这样指定的,但任务可能都在一个线程上运行,所以如果另一个任务阻碍了你的任务,你的任务可能不会以确切的指定时间间隔运行。
  3. 您的TimerTask 是否与 UI 事件循环正确同步(即,它是否以正确的runLater() 或黑莓 UI 提供的任何方法更新标签)?如果您不这样做,UI 事件循环可能不会注意到您已更改标签。我认为在 Blackberry 上,正确的是 invokeLater()invokeAndWait(),这取决于您要完成的任务。

在代码发布后编辑

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

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

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(),而前者没有。这可以解释为什么您的标签更改只是偶尔出现。

【讨论】:

  • 您好 Andersoj,我刚刚发布了我的代码。你能指出我可能错过了什么吗?谢谢。
  • 我已经尝试过“invokeLater()”并且得到了相同的结果,我可能需要测量计时器。非常感谢您的帮助。
  • @Tuyen Nguyen:让我们知道你发现了什么。
  • 我一定还缺少其他东西。这是应用程序的完整源代码:tuyennguyen.ca/data/blackberry/stopwatch/StopWatch.zip 该项目是使用 BlackBerry JDE Eclipse Plugin、JRE 5.0.0、模拟器 BlackBerry Storm 开发的。希望任何人都可以看到问题出在哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多