locked
Pause dans un Timer RRS feed

  • Question

  • Bonjour,

    Voici une question qui fait marcher la cervelle. En ajoutant nos neuronnes peut être qu'on trouvera la réponse... =)

    Pour lancer des tâches périodiquements, j'utilise la classe System.Threading.Timer. Rien de bien compliqué jusque là.
    Seulement, dans certains cas j'ai besoin de faire une pause sur les objets en questions.

    Par exemple, si ma tâche s'exécute toutes les 3 secondes, et que la pause se fait entre ces exécutions (1 seconde), il faudra que ça reprenne là ou ça c'est arrété (donc reste 2 secondes avant exécution).

    Et pas trouvé de moyen "clair" pour effectuer cette action. Existe t'il ? Ou alors n'est ce pas la bonne classe à utiliser ?

    Information complémentaire : c'est une app XNA.

    Merci à vous !

    Damien



    mardi 2 octobre 2012 09:01

Réponses

  • Ce n'est pas possible avec le timer du SDK, ceci dit c'est facile d'en faire un soi même (il suffit de récupérer le temps restant avant la pause

    using System;
    using System.Threading;
    
    public class PausableTimer {
      public event EventHandler Elapsed;
      private Timer mTimer;
      private bool mEnabled;
      private int mResidue;
      private DateTime mStart;
      private object mLocker;
    
      public PausableTimer() {
        mTimer = new Timer(callback);
        mLocker = new object();
      }
    
      public int Interval { get; set; }
      
      public bool Enabled {
        get { return mEnabled; }
        set {
          lock (mLocker) {
            if (value == mEnabled) return;
            mEnabled = value;
            if (value) {
              mStart = DateTime.Now;
              mTimer.Change(Interval - mResidue, Interval);
            }
            else {
              mTimer.Change(0, 0);
              mResidue = Math.Min(Interval, (int)(DateTime.Now - mStart).TotalMilliseconds);
            }
          }
        }
      }
    
      public void Reset() {
        lock (mLocker) {
          Enabled = false;
          mResidue = 0;
        }
      }
    
      private void callback(object dummy) {
        bool fire;
        lock (mLocker) {
          mStart = DateTime.Now;
          fire = Elapsed != null && mEnabled;
        }
        try {  // System.Timers.Timer.Elapsed swallows exceptions, bah
          if (fire) Elapsed(this, EventArgs.Empty);
        }
        catch { }
      }
    }

    copie colle ca dans ton projet et utilise le PausableTimer à la place du Timer ;)


    S'il vous plaît n'oublier pas de marquer la ou les réponses qui aident à résoudre votre problème. Pour que la discussion puisse être marquée comme résolue

    • Marqué comme réponse Frontier. _ mardi 2 octobre 2012 21:26
    mardi 2 octobre 2012 09:17

Toutes les réponses

  • Ce n'est pas possible avec le timer du SDK, ceci dit c'est facile d'en faire un soi même (il suffit de récupérer le temps restant avant la pause

    using System;
    using System.Threading;
    
    public class PausableTimer {
      public event EventHandler Elapsed;
      private Timer mTimer;
      private bool mEnabled;
      private int mResidue;
      private DateTime mStart;
      private object mLocker;
    
      public PausableTimer() {
        mTimer = new Timer(callback);
        mLocker = new object();
      }
    
      public int Interval { get; set; }
      
      public bool Enabled {
        get { return mEnabled; }
        set {
          lock (mLocker) {
            if (value == mEnabled) return;
            mEnabled = value;
            if (value) {
              mStart = DateTime.Now;
              mTimer.Change(Interval - mResidue, Interval);
            }
            else {
              mTimer.Change(0, 0);
              mResidue = Math.Min(Interval, (int)(DateTime.Now - mStart).TotalMilliseconds);
            }
          }
        }
      }
    
      public void Reset() {
        lock (mLocker) {
          Enabled = false;
          mResidue = 0;
        }
      }
    
      private void callback(object dummy) {
        bool fire;
        lock (mLocker) {
          mStart = DateTime.Now;
          fire = Elapsed != null && mEnabled;
        }
        try {  // System.Timers.Timer.Elapsed swallows exceptions, bah
          if (fire) Elapsed(this, EventArgs.Empty);
        }
        catch { }
      }
    }

    copie colle ca dans ton projet et utilise le PausableTimer à la place du Timer ;)


    S'il vous plaît n'oublier pas de marquer la ou les réponses qui aident à résoudre votre problème. Pour que la discussion puisse être marquée comme résolue

    • Marqué comme réponse Frontier. _ mardi 2 octobre 2012 21:26
    mardi 2 octobre 2012 09:17
  • Nickel !!

    Je viens de tester et ça répond tout à fait.
    J'aimerai bien qu'on me mache le travail comme ça pour toute une partie du développement. Ca me ferait gagner pas mal de temps. :p

    Merci !
    mardi 2 octobre 2012 21:26