暂停System.Timers.Timer的正确方法?

时间:2009-04-14 18:51:29

标签: .net vb.net timer

我正在研究如何暂停System.Timers.Timer,我无法找到在不重置计时器的情况下暂停它的正确方法。

如何暂停?

6 个答案:

答案 0 :(得分:6)

没有Pause(),你可以在Pause()上写一个:

  1. 更改(Timeout.Infinite,Timeout.Infinite)
  2. 保存计算剩余的计时器数量。
  3. on Resume():

    1. 更改(剩余计时器数量)
    2. 如果您编写此类,请将其发布回答,因为我们很多人似乎都需要Timer类中的这些功能。 :)

答案 1 :(得分:3)

我现在知道了,我确定它不是防弹的,所以告诉我它有什么问题......

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

答案 2 :(得分:0)

你应该遵循Shay Erlichmen给出的建议。您需要在暂停时保存剩余时间,并在计时器恢复时从该点继续。至于你当前的代码有什么问题:

Me.Interval = Me.Interval - sw.ElapsedMilliseconds

上面的代码将确保您下次恢复它将在第一个刻度上按预期工作,但在连续刻度上,您将有Me.Interval - sw.ElapsedMilliseconds作为间隔而不是原始设置间隔。

答案 3 :(得分:0)

这是我一直在使用的。它可能不是最先进的准确但工作得很好。至少,对于试图在计时器暂停/恢复的人来说,这是一个很好的起点。

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

答案 4 :(得分:0)

基于sveilleux2和Tomerz的先前评论,我改进了解决方案,以实现IDisposable,允许多个暂停恢复调用以及添加Enabled和Paused属性。

// fail 1
// text is owned by main document:  false
// --------------
// success 2
// --------------
// fail 3
// text is owned by main document:  true
// --------------
// success 4
// --------------

答案 5 :(得分:-1)

创建一个这样的计时器:

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

    }

您可以设置此属性以启动或暂停计时器执行timeEvent:

开始:

    t.Enabled = true 

暂停:

    t.Enabled = false