2009-04-14 26 views
6

Sprawdzam, jak zatrzymać się na System.Timers.Timer i nie mogę znaleźć prawidłowego sposobu na zatrzymanie go bez resetowania licznika czasu.Właściwy sposób wstrzymania System.Timers.Timer?

Jak zatrzymać?

+0

Wracam do domu, więc wracam za około godzinę, żeby zobaczyć, co mam odpowiedź. – Fredou

+0

sw powinno być _sw. –

+0

Nie wiem, czy zaktualizowałbym interwał w pauzie(), po prostu mógłbym zachować wartość jako prywatną. –

Odpowiedz

3

mam, że na razie, jestem pewien, że to nie jest kuloodporny więc powiedz mi, co jest nie tak ...

Public Class ImprovedTimer 
Inherits System.Timers.Timer 

Private _sw As System.Diagnostics.Stopwatch 
Private _paused As Boolean 
Private _originalInterval As Double 
Private _intervalRemaining As Double? 

Public ReadOnly Property IntervalRemaining() As Double? 
    Get 
     Return _intervalRemaining 
    End Get 
End Property 

Public ReadOnly Property Paused() As Boolean 
    Get 
     Return _paused 
    End Get 
End Property 

Public ReadOnly Property OriginalInterval() As Double 
    Get 
     Return _originalInterval 
    End Get 
End Property 

Public Sub Pause() 
    If Me.Enabled Then 
     _intervalRemaining = Me.Interval - _sw.ElapsedMilliseconds 
     _paused = True 
     resetStopWatch(False, False) 
     MyBase.Stop() 
    End If 
End Sub 

Public Sub [Resume]() 
    If _paused Then 
     Me.Interval = If(_intervalRemaining.HasValue, _intervalRemaining.Value, _originalInterval) 
     resetStopWatch(True, False) 
     MyBase.Start() 
    End If 
End Sub 

Public Overloads Property Enabled() As Boolean 
    Get 
     Return MyBase.Enabled 
    End Get 
    Set(ByVal value As Boolean) 
     MyBase.Enabled = value 
     resetStopWatch(MyBase.Enabled, True) 
    End Set 
End Property 

Public Overloads Sub Start() 
    resetStopWatch(True, True) 
    MyBase.Start() 
End Sub 

Public Overloads Sub [Stop]() 
    resetStopWatch(False, True) 
    MyBase.Stop() 
End Sub 

Public Overloads Property Interval() As Double 
    Get 
     Return MyBase.Interval 
    End Get 
    Set(ByVal value As Double) 
     MyBase.Interval = value 
     If Not _paused Then 
      _originalInterval = MyBase.Interval 
     End If 
    End Set 
End Property 

Private Sub resetStopWatch(ByVal startNew As Boolean, ByVal resetPause As Boolean) 
    If _sw IsNot Nothing Then 
     _sw.Stop() 
     _sw = Nothing 
    End If 
    If resetPause Then 
     If _paused Then 
      Me.Interval = _originalInterval 
     End If 
     _paused = False 
     _intervalRemaining = Nothing 
    End If 
    If startNew Then 
     _sw = System.Diagnostics.Stopwatch.StartNew 
    End If 
End Sub 

Private Sub ImprovedTimer_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed 
    resetStopWatch(False, True) 
End Sub 

Private Sub ImprovedTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles Me.Elapsed 
    resetStopWatch(Me.AutoReset, True) 
End Sub 

End Class 
6

Nie ma pauzy(), można napisać, że jeden na Pause():

  1. Zmian (Timeout.Infinite, Timeout.Infinite)
  2. Zapisz obliczenia kwoty Czas pozostały.

na Resume():

  1. Change (ilość Czas pozostały)

Jeśli piszesz tej klasy proszę umieszczać go w odpowiedzi, jak wydaje się, że wielu z nas potrzebuje tej funkcjonalności z klasy Timer. :)

+0

Po prostu to zrobiłem, jak myślisz? powrót w 1 godzinę – Fredou

0

Powinieneś przestrzegać wskazówek udzielonych przez Shay Erlichmen. Będziesz musiał zaoszczędzić czas pozostały do ​​zatrzymania i kontynuować od tego momentu, gdy timer zostanie wznowiony. Jeśli chodzi o to, co jest nie tak z bieżącego kodu:

Me.Interval = Me.Interval - sw.ElapsedMilliseconds 

Powyższy kod będzie upewnić się, że następnym razem, gdy wznowienie będzie działać zgodnie z przeznaczeniem na pierwszym kleszcza, ale na continouos kleszcze musisz Me.Interval - sw.ElapsedMilliseconds jako interwał zamiast pierwotnego ustawionego interwału.

+0

spójrz na koniec klasy dla sub Prywatne Sub ImprovedTimer_Elapsed – Fredou

-1

Tworzenie timer tak:

System.Timers.Timer t = new System.Timers.Timer(1000) 
    t.Elapsed += new System.Timers.ElapsedEventHandler(timerEvent); 

    public void timerEvent(object source, System.Timers.ElapsedEventArgs e) 
    { 

    } 

co możliwe ustawić tę właściwość, aby uruchomić lub zatrzymać timer wykonać TimeEvent:

start:

t.Enabled = true 

Pauza:

t.Enabled = false 
+0

Wyłączenie/Włączenie faktycznie resetuje timer. Jeśli więc interwał czasowy wynosi 10 sekund, a wyłączysz go po 5 sekundach, po ponownym włączeniu zacznie działać od 10 sekund, a nie od 5 sekund. – sveilleux2

0

Oto co używam. Być może nie jest to najnowocześniejsza dokładność, ale działa całkiem nieźle. Przynajmniej jest to dobry punkt wyjścia dla kogoś, kto próbuje wstrzymać/wznowić działanie timera.

public class PausableTimer 
{ 
    private Timer _timer; 
    private Stopwatch _stopWatch; 
    private bool _paused; 
    private double _interval; 
    private double _remainingTimeBeforePause; 

    public PausableTimer(double interval, ElapsedEventHandler handler) 
    { 
     _interval = interval; 
     _stopWatch = new Stopwatch(); 

     _timer = new Timer(interval); 
     _timer.Elapsed += (sender, arguments) => { 
      if (handler != null) 
      { 
       if(_timer.AutoReset) 
       { 
        _stopWatch.Restart(); 
       } 

       handler(sender, arguments); 
      } 
     }; 

     _timer.AutoReset = false; 
    } 

    public bool AutoReset 
    { 
     get 
     { 
      return _timer.AutoReset; 
     } 
     set 
     { 
      _timer.AutoReset = value; 
     } 
    } 

    public void Start() 
    { 
     _timer.Start(); 
     _stopWatch.Restart(); 
    } 

    public void Stop() 
    { 
     _timer.Stop(); 
     _stopWatch.Stop(); 
    } 

    public void Pause() 
    { 
     if(!_paused && _timer.Enabled) 
     { 
      _stopWatch.Stop(); 
      _timer.Stop(); 
      _remainingTimeBeforePause = Math.Max(0, _interval - _stopWatch.ElapsedMilliseconds); 
      _paused = true; 
     } 
    } 

    public void Resume() 
    { 
     if(_paused) 
     { 
      _paused = false; 
      if(_remainingTimeBeforePause > 0) 
      { 
       _timer.Interval = _remainingTimeBeforePause; 
       _timer.Start(); 
      } 
     } 
    } 
} 
+0

Wiem, że jest trochę późno, ale kilka komentarzy. 1. Aby obsługiwać multi pause-resume, dodaj _stopWatch.Początek(); do wznowienia() po _timer.Start(); 2. dla wersji .net przed wersją 4.0 zastąpić _stopWatch.Restart(); z _stopWatch = Stopwatch.StartNew(); 3. Usunąłem ElapsedEventHandler z konstruktora i dodałem publiczne wydarzenie ElapsedEventHandler Elapsed; , aby dopasować oryginalne zachowanie. Dzięki za urywek. wykonuje zadanie. – Tomerz

Powiązane problemy