Comment réinitialiser une minuterie en C #?

114

Il y a trois Timercatégories que je suis au courant, System.Threading.Timer, System.Timers.Timeret System.Windows.Forms.Timer, mais aucun d' entre eux ont une .Reset()fonction qui réinitialiser le temps écoulé actuel à 0.

Existe-t-il une classe BCL qui possède cette fonctionnalité? Existe-t-il un moyen non piraté de le faire? (Je pensais que changer la limite de temps pourrait le réinitialiser) Vous avez pensé à quel point il serait difficile de réimplémenter une Timerclasse qui avait cette fonctionnalité, ou comment le faire de manière fiable avec l'une des classes BCL?

Matthew Scharley
la source
3
En utilisant la solution de JP, utilisez une méthode d'extension
benPearce
J'ai aussi le même besoin de réinitialisation et pour les mêmes raisons que celles mentionnées, FileSystemWatcher est désagréable et peu pratique à utiliser
John Lewin
Si vous utilisez Chronomètre pour une minuterie et utilisez la réponse de la méthode d'extension, soyez prudent car la méthode d'extension Stopwatch.Restart arrive dans .NET 4.0. msdn.microsoft.com/en-us/library/…
si618

Réponses:

148

Je fais toujours ...

myTimer.Stop();
myTimer.Start();

... est-ce un hack? :)

Par commentaire, sur Threading.Timer, c'est la méthode Change ...

dueTime Type: System.Int32délai avant l'invocation de la méthode de rappel spécifiée lors de la construction du Timer, en millisecondes. Spécifier Timeout.Infinite pour empêcher le redémarrage du minuteur. Spécifiez zéro (0) pour redémarrer immédiatement le minuteur.

JP Alioto
la source
L'autre problème est que seuls les problèmes avec Forms.Timer, et mon application n'a pas d'interface graphique (Application.Start () sans paramètres), donc JE PENSE que la classe Threading.Timer est meilleure pour d'autres raisons, mais bon point.
Matthew Scharley
3
@Matthew: Voir msdn.microsoft.com/en-us/magazine/cc164015.aspx pour une discussion sur les différentes classes de minuterie et pour savoir si leur utilisation est appropriée. En général, cependant, Forms.Timerne doit être utilisé qu'avec une interface graphique. Cependant, en plus Forms.Timeret Threading.Timeril y a aussi Timers.Timer.
Brian
60

Tous les minuteurs ont l'équivalent des méthodes Start () et Stop (), à l'exception de System.Threading.Timer.

Donc, une méthode d'extension telle que ...

public static void Reset(this Timer timer)
{
  timer.Stop();
  timer.Start();
}

... est une façon de procéder.

Dan
la source
1
Je ne cherche pas à mesurer le temps écoulé. Mon cas d'utilisation exact pour cela est que j'ai un FileSystemWatcher qui surveille un répertoire et que je veux attraper des groupes de modifications (c'est-à-dire, des modifications apportées par exemple à 5 secondes les unes des autres). La théorie étant que le premier changement démarre une minuterie qui est réinitialisée à chaque changement jusqu'à ce qu'elle se déclenche et ferme le groupe.
Matthew Scharley
Ouais, je l'ai repéré quand j'ai relu ta question. J'ai modifié ma réponse.
Dan
Cela fonctionne et il est important de noter que cela ne fonctionnera pas si vous appelez uniquement timer.Start(). J'ai fait cette requête Linqpad pour la tester. Essayez de l'enlever timer.Stopet vous verrez la différence.
Jared Beach
30

Pour System.Timers.Timer, selon la documentation MSDN, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Si l'intervalle est défini après le démarrage de la minuterie, le décompte est réinitialisé. Par exemple, si vous définissez l'intervalle sur 5 secondes, puis définissez la propriété Enabled sur true, le décompte commence au moment où Enabled est défini. Si vous réinitialisez l'intervalle à 10 secondes lorsque le compte est de 3 secondes, l'événement Elapsed est déclenché pour la première fois 13 secondes après que Enabled a été défini sur true.

Alors,

    const double TIMEOUT = 5000; // milliseconds

    aTimer = new System.Timers.Timer(TIMEOUT);
    aTimer.Start();     // timer start running

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer
mMontu
la source
1
Le problème ici est que vous ne savez pas toujours au moment où vous souhaitez réinitialiser si la minuterie fonctionne déjà ou non. Donc, vous devriez faire aTimer.Interval = TIMEOUT et aTimer.Start (). Donc dans l'ensemble, une fonction de réinitialisation ci-dessus utilise moins de lignes et de variables. Excellent ajout cependant.
e-motiv
1
@ RU-Bn L'OP indique clairement " une fonction .Reset () qui remettrait le temps écoulé actuel à 0 ". - il ne mentionne pas qu'il est destiné à être utilisé sur une application mal conçue où vous ne savez même pas si le minuteur fonctionne. Vérifiez également le commentaire de l'auteur (il y a plus de 4 ans): " La théorie étant que le premier changement démarre un minuteur qui se réinitialise à chaque changement jusqu'à ce qu'il se déclenche finalement et ferme le groupe. ". Merci pour le vote négatif, en tout cas.
mMontu
J'ai vu aussi un problème comme ça. Ce que j'ai fait est: aTimer.Interval = aTimer.Interval. Cela a déclenché la boucle. Beats me why but it works ...
Herman Van Der Blom
7

Vous pouvez écrire une méthode d'extension appelée Reset (), qui

  • appelle Stop () - Start () pour Timers.Timer et Forms.Timer
  • appelle Change for Threading.Timer
Gishu
la source
5

Je viens d'attribuer une nouvelle valeur à la minuterie:

mytimer.Change(10000, 0); // reset to 10 seconds

Ça fonctionne bien pour moi.

en haut du code définissez la minuterie: System.Threading.Timer myTimer;

if (!active)
        {
            myTimer= new System.Threading.Timer(new TimerCallback(TimerProc));
        }
        myTimer.Change(10000, 0);
        active = true;

private void TimerProc(object state)
    {
        // The state object is the Timer object.
        System.Threading.Timer t = (System.Threading.Timer)state;
        t.Dispose();
        Console.WriteLine("The timer callback executes.");
        active = false;
        //action to do when timer is back to zero
    }
Quispie
la source
5

Pour plus de clarté puisque certains autres commentaires sont incorrects, lorsque vous utilisez le System.Timersparamètre Enabled sur true , le temps écoulé est réinitialisé. Je viens de tester le comportement avec ce qui suit:

Timer countDown= new Timer(3000);

Main()
{
    TextBox.TextDidChange += TextBox_TextDidChange;
    countdown.Elapsed += CountDown_Elapsed;
}

void TextBox_TextDidChange(Object sender, EventArgs e)
{
    countdown.Enabled = true;
}

void CountDown_Elapsed(object sender, EventArgs e)
{
    System.Console.WriteLine("Elapsed");
}

Je saisissais du texte dans la zone de texte à plusieurs reprises et le minuteur ne fonctionnerait que 3 secondes après la dernière frappe. C'est également indiqué dans la documentation, comme vous le verrez: l'appel Timers.Start()définit simplement Enabled sur true.

Et pour être sûr, ce à quoi j'aurais dû aller directement depuis le début, vous verrez dans la source de référence .NET que si vous activez un minuteur déjà activé, il appelle la UpdateTimer()méthode privée , qui appelle en interne Change().

NickSpag
la source
Non vous vous trompez. La UpdateTtimerméthode privée est appelée si et seulement si la valeur actuelle de Enabledn'est pas égale à la nouvelle value.
Nicolò Carandini le
3

Pour un minuteur (System.Windows.Forms.Timer).

Les méthodes .Stop, puis .Start fonctionnaient comme une réinitialisation.

elmsoftware
la source
1

Une autre façon alternative de réinitialiser le windows.timer consiste à utiliser le compteur, comme suit:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

private void mTimer_Tick()
{
  tmrCtr++;
  //perform task
}  

Donc, si vous avez l'intention de répéter toutes les 1 seconde, vous pouvez régler l'intervalle de minuterie à 100 ms et tester le compteur à 10 cycles.

Cela convient si le temporisateur doit attendre certains processus, ceux-ci peuvent être terminés à des intervalles de temps différents.

Ivan
la source
1

je fais ça

//Restart the timer
queueTimer.Enabled = true;
Rissa
la source
Cela le permet simplement. Même si elle a été désactivée au préalable, la réactivation ne change pas le temps écoulé qui avait été collecté jusqu'à ce point.
vapcguy
1

Tu peux faire timer.Interval = timer.Interval

Ella Sharakanski
la source