Jak zresetować licznik czasu w C #?

114

Istnieją trzy Timerklasy, że jestem świadom, System.Threading.Timer, System.Timers.Timer, i System.Windows.Forms.Timer, ale żaden z nich posiada .Reset()funkcję, która będzie zresetować aktualny czas, jaki upłynął do 0.

Czy istnieje klasa BCL, która ma taką funkcjonalność? Czy można to zrobić w inny sposób niż hack? (Pomyślałem, że być może zmiana limitu czasu może go zresetować). Zastanawiałem się, jak trudno byłoby ponownie zaimplementować Timerklasę, która ma tę funkcjonalność, lub jak zrobić to niezawodnie z jedną z klas BCL?

Matthew Scharley
źródło
3
Korzystając z rozwiązania JP, użyj metody rozszerzenia
benPearce,
Ja też mam taką samą potrzebę resetowania iz tych samych powodów, o których wspomniałem, FileSystemWatcher jest nieprzyjemny i niewygodny w użyciu
John Lewin
Jeśli używasz Stopwatch jako czasomierza i korzystasz z odpowiedzi na metodę rozszerzającą, bądź ostrożny, ponieważ metoda rozszerzenia Stopwatch.Restart jest dostępna w .NET 4.0. msdn.microsoft.com/en-us/library/…
si618

Odpowiedzi:

149

Zawsze to robię ...

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

... czy to hack? :)

Zgodnie z komentarzem w Threading.Timer, to metoda Change ...

dueTime Type: System.Int32ilość czasu do opóźnienia przed wywołaniem metody wywołania zwrotnego określonej podczas konstruowania Timer, w milisekundach. Określ, Timeout.Infiniteaby zapobiec ponownemu uruchomieniu licznika czasu. Określ zero (0), aby natychmiast ponownie uruchomić licznik czasu.

JP Alioto
źródło
Innym problemem jest to, że działa tylko z Forms.Timer, a moja aplikacja nie ma GUI (Application.Start () bez parametrów), więc myślę, że klasa Threading.Timer jest lepsza z innych powodów, ale słuszna uwaga.
Matthew Scharley,
3
@Matthew: Zobacz msdn.microsoft.com/en-us/magazine/cc164015.aspx, aby zapoznać się z omówieniem różnych klas liczników czasu i ich stosownością. Ogólnie jednak Forms.Timerpowinno być używane tylko z graficznym interfejsem użytkownika. Jednak oprócz Forms.Timeri Threading.Timerjest też Timers.Timer.
Brian
60

Wszystkie liczniki czasu mają odpowiedniki metod Start () i Stop (), z wyjątkiem System.Threading.Timer.

Więc metoda rozszerzenia, taka jak ...

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

... jest jednym ze sposobów, aby to osiągnąć.

Dan
źródło
1
Nie chcę mierzyć upływającego czasu. Mój dokładny przypadek użycia jest taki, że mam FileSystemWatcher obserwujący katalog i chcę wychwycić grupy zmian (tj. Zmiany dokonane w ciągu na przykład 5s od siebie). Teoria głosi, że pierwsza zmiana uruchamia licznik czasu, który jest resetowany przy każdej zmianie, aż w końcu odpala i zamyka grupę.
Matthew Scharley,
Tak, zauważyłem to, kiedy ponownie przeczytałem twoje pytanie. Zredagowałem moją odpowiedź.
Dan
To działa i ważne jest, aby pamiętać, że nie zadziała, jeśli tylko zadzwonisz timer.Start(). Zrobiłem to zapytanie Linqpad, aby to przetestować. Spróbuj go usunąć timer.Stop, a zobaczysz różnicę.
Jared Beach
30

Na System.Timers.Timerwedług dokumentacji MSDN http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Jeśli interwał zostanie ustawiony po uruchomieniu timera, licznik zostanie zresetowany. Na przykład jeśli ustawisz interwał na 5 sekund, a następnie ustawisz właściwość Enabled na true, liczenie rozpocznie się w momencie ustawienia Enabled. Jeśli zresetujesz interwał do 10 sekund, gdy count wynosi 3 sekundy, zdarzenie Elapsed zostanie zgłoszone po raz pierwszy 13 sekund po ustawieniu Enabled na true.

Więc,

    const double TIMEOUT = 5000; // milliseconds

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

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer
mMontu
źródło
1
Problem polega na tym, że nie zawsze wiesz, że chcesz zresetować, czy timer już działa, czy nie. Więc musiałbyś zrobić aTimer.Interval = TIMEOUT i aTimer.Start (). Podsumowując, powyższa funkcja resetowania wykorzystuje mniej linii i zmiennych. Świetny dodatek.
e-motiv
1
@ RU-Bn OP wyraźnie stwierdza " a .Reset () funkcja, która zresetuje bieżący upływający czas do 0. " - nie wspomina o tym, że jest przeznaczony do użytku w źle zaprojektowanej aplikacji, w której nawet nie wiesz, czy timer jest uruchomiony. Sprawdź także komentarz autora (ponad 4 lata temu): „ Teoria mówi, że pierwsza zmiana uruchamia licznik czasu, który jest resetowany przy każdej zmianie, aż w końcu odpala i zamyka grupę. ”. W każdym razie dzięki za głosowanie negatywne.
mMontu
Widziałem też taki problem. To, co zrobiłem, to: aTimer.Interval = aTimer.Interval. To spowodowało, że pętla się trwała. Bije mi dlaczego, ale działa ...
Herman Van Der Blom
7

Możesz napisać metodę rozszerzającą o nazwie Reset (), która

  • wywołuje Stop () - Start () dla Timers.Timer i Forms.Timer
  • wywołuje Change for Threading.Timer
Gishu
źródło
5

Właśnie przypisałem nową wartość do timera:

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

to działa dobrze dla mnie.

u góry kodu zdefiniuj licznik czasu: 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
źródło
5

Dla jasności, ponieważ niektóre inne komentarze są niepoprawne, użycie System.Timersustawienia Enabled na true spowoduje zresetowanie czasu, który upłynął. Właśnie przetestowałem zachowanie z poniższym:

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

Wielokrotnie wprowadzałem tekst do pola tekstowego, a licznik czasu działałby tylko 3 sekundy po ostatnim naciśnięciu klawisza. Jest to również zasugerowane w dokumentach, jak zobaczysz: wywołanie Timers.Start()po prostu ustawia Enabled na true.

I dla pewności, do czego powinienem od razu przejść od samego początku, w źródle referencyjnym .NET zobaczysz, że jeśli włączysz już włączony licznik czasu, wywoła on UpdateTimer()metodę prywatną , która wywołuje wewnętrznie Change().

NickSpag
źródło
Nie, mylisz się. Metoda prywatna UpdateTtimerjest wywoływana wtedy i tylko wtedy, gdy bieżąca wartość Enablednie jest równa new value.
Nicolò Carandini
3

Dla timera (System.Windows.Forms.Timer).

Metody .Stop, a następnie .Start działały jako reset.

elmsoftware
źródło
1

Innym alternatywnym sposobem resetowania windows.timer jest użycie licznika w następujący sposób:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

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

Jeśli więc zamierzasz powtarzać co 1 sekundę, możesz ustawić interwał timera na 100 ms i przetestować licznik na 10 cykli.

Jest to odpowiednie, jeśli licznik czasu ma czekać na niektóre procesy, które mogą zostać zakończone w innym przedziale czasu.

ivan
źródło
1

robię to

//Restart the timer
queueTimer.Enabled = true;
Rissa
źródło
To po prostu to umożliwia. Nawet jeśli zostało wcześniej wyłączone, ponowne włączenie nie zmienia czasu, który upłynął, który został zebrany do tego momentu.
vapcguy
1

Możesz to zrobić timer.Interval = timer.Interval

Ella Sharakanski
źródło