Proper way to pause a System.Timers.Timer?

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. :)


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

Tags:

.Net

Vb.Net

Timer