tags:

views:

1609

answers:

4

I'm looking at how to pause a System.Timers.Timer and I cannot figure out the proper way to pause it without resetting the timer.

How to pause it?

A: 
timer.Change( Timeout.Infinite, Timeout.Infinite );

Will do it for you.

Edit:

Just read your question again, as far as I'm aware you can't pause the way you want out of the box. I'm afraid you'll have to save the remaining time, if you want to pause, and be able to start again, without resetting.

Arkain
+1  A: 

There is no Pause(), you can write one that on Pause():

  1. Change(Timeout.Infinite, Timeout.Infinite)
  2. Save the calculate the amount of timer remaining.

on Resume():

  1. Change(amount of timer remaining)

If you write this class please post it in answer as it seem that many of us need that functionality out of the Timer class. :)

Shay Erlichmen
I just did it, what do you think? back in 1 hour
Fredou
A: 

You should follow the advice Shay Erlichmen gave. You'll need to save the time remaining when pausing, and continue from that point when the timer is resumed. As for what is wrong with your current code:

Me.Interval = Me.Interval - sw.ElapsedMilliseconds

The above code will make sure that next time you resume it will work as intended on the first tick, but on the continouos ticks you'll have Me.Interval - sw.ElapsedMilliseconds as the interval instead of the original set interval.

Qua
look at the end of the class for the sub Private Sub ImprovedTimer_Elapsed
Fredou
A: 

I got that for now, I'm sure it's not bulletproof so tell me what is wrong with it...

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
Fredou