2010-11-03 22 views
1

Je suis en train d'écrire une application de chronométrage pour BlackBerry (similaire au StopWatch intégré de BlackBerry). Il y a une étiquette de minuterie affichant l'heure actuelle au format MM: SS: T (minutes, secondes, dixième de seconde). L'étiquette est actualisée toutes les 100 millisecondes avec TimerTask.TimerTask ne s'exécute pas à un intervalle prédéterminé

L'application fonctionne bien et l'heure est affichée correctement, cependant, il y a des moments où l'étiquette de la minuterie n'est pas mise à jour à l'intervalle prédéterminé (toutes les 100 millisecondes). L'étiquette de minuterie marque une pause (sans compter) pendant un moment et continue à compter (tout en affichant correctement l'heure)

Je pense que la TimerTask n'est pas exécutée pour mettre à jour l'étiquette de la minuterie pendant cette pause. Savez-vous pourquoi l'application agit de cette façon et comment y remédier?

Voici le fil pour mettre à jour l'étiquette de la minuterie:

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

le TimerTask:

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

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

et la méthode iUpdateTimerLabel:

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

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

Suggère que vous postez le code pour votre 'TimerTask' ainsi que le code qui le soumet au' Timer' – andersoj

+0

Cela n'a probablement rien à voir avec le timer, en particulier. Voir connexes: http://stackoverflow.com/questions/2569468/how-do-i-update-blackberry-ui-items-from-a-thread – andersoj

Répondre

2

premier est de mesurer .. notez les horodatages quand votre timertask commence et se termine, et voyez si c'est vraiment le TimerTask qui ' s vraiment le problème. Avec cela à la main, deux choses qui me viennent sont,

  1. est votre tâche de blocage (peut-être quelque chose sur UI)?
  2. Y a-t-il d'autres tâches dans la même instance Timer? Je ne sais pas si cela est spécifié en tant que tel, mais les tâches s'exécutent probablement toutes sur un seul thread, donc si une autre tâche entrave, vos tâches peuvent ne pas s'exécuter à l'intervalle spécifié.
  3. Votre TimerTask est-il correctement synchronisé avec la boucle d'événements de l'interface utilisateur (c'est-à-dire, met-il à jour l'étiquette dans le bon runLater() ou quelle que soit la méthode fournie par l'interface BlackBerry Blackberry)? Si vous ne le faites pas, la boucle d'événements de l'interface utilisateur peut ne pas remarquer que vous avez modifié l'étiquette. Je pense que sur le Blackberry, la bonne chose est invokeLater() ou peut-être invokeAndWait(), en fonction de ce que vous essayez d'accomplir.

Edité après le code affiché:

Quelques ressources pertinentes et utiles sont here.

  1. OK, je encore dire à l'instrument de votre code avec des appels de journalisation ou println à la sortie horodatages lors de son exécution.
  2. Je ne sais pas pourquoi l'appel schedule() est dans son propre Runnable ... vous n'avez pas besoin de cela, mais peut-être que votre application le fait pour une raison que je ne vois pas. Si vous pensez que vous créez un thread explicite pour le timer, vous ne l'êtes pas. Vous pouvez probablement simplement créer le Timer et appeler le schedule() à partir de n'importe quel thread d'application qui le configure. Timer contient un thread captif qui fera ce travail, et l'introduction de Yet Another Thread est probablement redondant et confus.
  3. Je pense toujours que vous voudrez peut-être faire quelque chose comme:
  4. Un autre rappel pour prendre la mesure réelle ce que la minuterie est en train de faire plutôt que de compter sur ma spéculation ...
Code

à l'intérieur du 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+" "); 
     } 
    }); 
} 

Votre appel synchronized peut suffire à empêcher les choses de grimper, mais ce n'est pas vraiment le moyen préféré. Si le fil Timer est dédié à ce seul but, comme il apparaît, vous pouvez probablement remplacer invokeLater() par invokeAndWait() si vous le souhaitez. Quelqu'un d'autre peut être en mesure d'expliquer la différence entre le verrouillage de l'interface utilisateur et le fonctionnement de l'interface utilisateur, mais je suppose que ce dernier force un invalidate(), mais pas le précédent. Cela expliquerait pourquoi les changements apportés à votre étiquette n'apparaissent que sporadiquement.

+0

Bonjour Andersoj, je viens de poster mon code. Pourriez-vous préciser ce que j'ai pu manquer quelque chose? Je vous remercie. –

+0

J'ai essayé "invokeLater()" et j'ai le même résultat, il se peut que je doive mesurer le timer. Merci en effet pour votre aide. –

+0

@Tuyen Nguyen: Dites-nous ce que vous trouvez. – andersoj