2009-04-14 22 views
6

Estoy viendo cómo pausar un System.Timers.Timer y no puedo encontrar la forma correcta de pausarlo sin reiniciar el temporizador.Forma correcta de pausar un System.Timers.Timer?

¿Cómo pausarlo?

+0

Me voy a casa tan cerca de 1 hora para ver qué respuesta obtuve .. – Fredou

+0

sw debería ser _sw. –

+0

No sé si actualizaría Interval en Pausa(), podría mantener el valor en privado. –

Respuesta

3

Tengo que, por ahora, estoy seguro de que no es a prueba de balas así que dime lo que está mal con él ...

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

No hay pausa(), se puede escribir que en Pausa():

  1. Cambio (Timeout.Infinite, Timeout.Infinite)
  2. Guardar el cálculo de la cantidad de temporizador restante.

en Reanudar():

  1. Cambio (cantidad de temporizador restante)

Si se escribe esta clase favor, puesto que en respuesta, ya que parece que muchos de nosotros necesitamos de la funcionalidad fuera de la clase Timer. :)

+0

Lo acabo de hacer, ¿qué opinas? de vuelta en 1 hora – Fredou

0

Debes seguir el consejo que dio Shay Erlichmen. Deberá guardar el tiempo restante al hacer una pausa y continuar desde ese punto cuando se reanude el temporizador. En cuanto a lo que está mal con su código actual:

Me.Interval = Me.Interval - sw.ElapsedMilliseconds 

El código anterior se asegurará de que la próxima vez que reanude su funcionamiento será el previsto en la primera marca, sino en las garrapatas continouos tendrá Me.Interval - sw.ElapsedMilliseconds como el intervalo en lugar del intervalo establecido originalmente.

+0

mira al final de la clase para el sub Sub privado ImprovedTimer_Elapsed – Fredou

-1

crear un temporizador así:

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) 
    { 

    } 

que pueda establecer esta propiedad para iniciar o detener el temporizador ejecute el timeEvent:

de inicio:

t.Enabled = true 

Pausa:

t.Enabled = false 
+0

Desactivar/Habilitar realmente restablecer el temporizador. Entonces, si el intervalo del temporizador es de 10 segundos y lo deshabilita a los 5 segundos, cuando lo habilita de nuevo, comenzará de nuevo desde 10 segundos y no desde 5 segundos. – sveilleux2

0

Aquí es lo que he estado usando. Tal vez no sea preciso, pero funciona bastante bien. Al menos, es un buen punto de partida para alguien que intenta pausar/reanudar en el temporizador.

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

Sé que es un poco tarde, pero hay pocos comentarios. 1. para admitir multi pausa-reanudar, agregar _stopWatch.Comienzo(); al currículum() después de _timer.Start(); 2. para las versiones .net anteriores v4.0 replace _stopWatch.Restart(); con _stopWatch = Stopwatch.StartNew(); 3. He eliminado ElapsedEventHandler del constructor y he añadido el evento público ElapsedEventHandler Elapsed; para que coincida con el comportamiento original. Gracias por el fragmento. hace el trabajo. – Tomerz

Cuestiones relacionadas