Wie setze ich einen Timer in C # zurück?

114

Es gibt drei TimerKlassen, die mir bekannt System.Threading.Timersind System.Timers.Timer, und System.Windows.Forms.Timer, aber keine davon hat eine .Reset()Funktion, die die aktuell verstrichene Zeit auf 0 zurücksetzen würde.

Gibt es eine BCL-Klasse mit dieser Funktionalität? Gibt es eine Non-Hack-Methode? (Ich dachte, eine Änderung des Zeitlimits könnte es möglicherweise zurücksetzen.) Überlegt, wie schwierig es wäre, eine TimerKlasse mit dieser Funktionalität erneut zu implementieren , oder wie man es zuverlässig mit einer der BCL-Klassen macht.

Matthew Scharley
quelle
3
Verwenden Sie die Lösung von JP, um eine Erweiterungsmethode zu verwenden
benPearce
Ich habe auch die gleiche Notwendigkeit zum Zurücksetzen und aus den gleichen genannten Gründen ist FileSystemWatcher unangenehm und unpraktisch zu bedienen
John Lewin
Wenn Sie Stopwatch als Timer verwenden und mit der Antwort auf die Erweiterungsmethode fortfahren, seien Sie vorsichtig, da die Erweiterungsmethode Stopwatch.Restart in .NET 4.0 enthalten ist. msdn.microsoft.com/en-us/library/…
si618

Antworten:

148

Mache ich immer ...

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

... ist das ein Hack? :) :)

Laut Kommentar auf Threading.Timer ist es die Änderungsmethode ...

dueTime Type: System.Int32Die Zeitspanne, die vor dem Aufrufen der beim Erstellen des Timers angegebenen Rückrufmethode in Millisekunden verzögert werden muss. Geben Sie Timeout.Infinitean, um einen Neustart des Timers zu verhindern. Geben Sie Null (0) an, um den Timer sofort neu zu starten.

JP Alioto
quelle
Das andere Problem ist, dass nur mit Forms.Timer gearbeitet wird und meine App keine GUI (Application.Start () ohne Parameter) hat. Daher denke ich, dass die Threading.Timer-Klasse aus anderen Gründen besser ist, aber ein guter Punkt.
Matthew Scharley
3
@Matthew: Unter msdn.microsoft.com/en-us/magazine/cc164015.aspx finden Sie eine Erläuterung der verschiedenen Timer-Klassen und deren Verwendung. Im Allgemeinen Forms.Timersollte jedoch nur mit einer GUI verwendet werden. Doch neben Forms.Timerund Threading.Timergibt es auch Timers.Timer.
Brian
60

Alle Timer mit Ausnahme von System.Threading.Timer entsprechen den Methoden Start () und Stop ().

Also eine Erweiterungsmethode wie ...

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

... ist ein Weg, dies zu tun.

Dan
quelle
1
Ich möchte die verstrichene Zeit nicht messen. Mein genauer Anwendungsfall hierfür ist, dass ich einen FileSystemWatcher habe, der ein Verzeichnis überwacht und Gruppen von Änderungen abfangen möchte (dh Änderungen, die beispielsweise innerhalb von 5 Sekunden voneinander vorgenommen wurden). Die Theorie besagt, dass die erste Änderung einen Timer startet, der bei jeder Änderung zurückgesetzt wird, bis sie schließlich ausgelöst und die Gruppe geschlossen wird.
Matthew Scharley
Ja, das habe ich entdeckt, als ich Ihre Frage noch einmal gelesen habe. Ich habe meine Antwort bearbeitet.
Dan
Dies funktioniert und es ist wichtig zu beachten, dass dies nicht funktioniert, wenn Sie nur anrufen timer.Start(). Ich habe diese Linqpad-Abfrage durchgeführt , um sie zu testen. Versuchen Sie es zu entfernen timer.Stopund Sie werden den Unterschied sehen.
Jared Beach
30

Für System.Timers.Timernach MSDN - Dokumentation, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Wenn das Intervall nach dem Start des Timers eingestellt wird, wird der Zähler zurückgesetzt. Wenn Sie beispielsweise das Intervall auf 5 Sekunden festlegen und dann die Enabled-Eigenschaft auf true setzen, beginnt die Zählung zu dem Zeitpunkt, zu dem Enabled festgelegt wurde. Wenn Sie das Intervall auf 10 Sekunden zurücksetzen, wenn die Anzahl 3 Sekunden beträgt, wird das Ereignis "Verstrichen" zum ersten Mal 13 Sekunden nach dem Aktivieren von "Aktiviert" ausgelöst.

So,

    const double TIMEOUT = 5000; // milliseconds

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

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer
mMontu
quelle
1
Das Problem hierbei ist, dass Sie zum Zeitpunkt des Zurücksetzens nicht immer wissen, ob der Timer bereits läuft oder nicht. Sie müssten also aTimer.Interval = TIMEOUT und aTimer.Start () ausführen. Insgesamt verwendet eine Reset-Funktion oben weniger Zeilen und Variablen. Tolle Ergänzung.
E-Motiv
1
@ RU-Bn Das OP gibt eindeutig " eine .Reset () -Funktion an, die die aktuell verstrichene Zeit auf 0 zurücksetzen würde ." - Es wird nicht erwähnt, dass es für eine schlecht gestaltete Anwendung vorgesehen ist, bei der Sie nicht einmal wissen, ob der Timer läuft. Überprüfen Sie auch den Kommentar des Autors (vor mehr als 4 Jahren): " Die Theorie besagt, dass die erste Änderung einen Timer startet, der bei jeder Änderung zurückgesetzt wird, bis er schließlich ausgelöst und die Gruppe geschlossen wird. " Trotzdem danke für die Abwertung.
mMontu
Ich habe auch so ein Problem gesehen. Was ich getan habe ist: aTimer.Interval = aTimer.Interval. Das löste aus, dass die Schleife lief. Schlägt mich warum, aber es funktioniert ...
Herman Van Der Blom
7

Sie könnten eine Erweiterungsmethode namens Reset () schreiben, die

  • ruft Stop () - Start () für Timers.Timer und Forms.Timer auf
  • ruft Change for Threading.Timer auf
Gishu
quelle
5

Ich habe dem Timer gerade einen neuen Wert zugewiesen:

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

es funktioniert gut für mich.

Definieren Sie oben im Code den Timer: 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
quelle
5

Aus Gründen der Übersichtlichkeit wird die verstrichene Zeit zurückgesetzt , wenn die System.TimersEinstellung Enabled auf true gesetzt ist, da einige andere Kommentare falsch sind . Ich habe das Verhalten gerade mit folgendem getestet:

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

Ich würde wiederholt Text in das Textfeld eingeben und der Timer würde nur 3 Sekunden nach dem letzten Tastendruck laufen. Wie Sie sehen werden, wird dies auch in den Dokumenten angedeutet: Timers.Start()Wenn Sie aufrufen, wird Enabled einfach auf true gesetzt.

Und um sicher zu sein, worauf ich von Anfang an hätte eingehen sollen, sehen Sie in der .NET-Referenzquelle, dass beim Aktivieren eines bereits aktivierten Timers die private UpdateTimer()Methode aufgerufen wird, die intern aufgerufen wird Change().

NickSpag
quelle
Nein, du liegst falsch. Die private UpdateTtimerMethode wird genau dann aufgerufen, wenn der aktuelle Wert von Enablednicht dem neuen entspricht value.
Nicolò Carandini
3

Für einen Timer (System.Windows.Forms.Timer).

Die Methoden .Stop und dann .Start fungierten als Reset.

elmsoftware
quelle
1

Eine andere alternative Möglichkeit zum Zurücksetzen von windows.timer ist die Verwendung des Zählers wie folgt:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

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

Wenn Sie also alle 1 Sekunde wiederholen möchten, können Sie das Timer-Intervall auf 100 ms einstellen und den Zähler auf 10 Zyklen testen.

Dies ist geeignet, wenn der Timer auf einige Prozesse warten soll, die möglicherweise zu einem anderen Zeitpunkt beendet werden.

ivan
quelle
1

Ich mache das

//Restart the timer
queueTimer.Enabled = true;
Rissa
quelle
Dies ermöglicht es nur. Selbst wenn es zuvor deaktiviert wurde, ändert das erneute Aktivieren nicht die verstrichene Zeit, die bis zu diesem Zeitpunkt gesammelt wurde.
Vapcguy
1

Du kannst tun timer.Interval = timer.Interval

Ella Sharakanski
quelle