2009-04-14 44 views
6

System.Timers.Timerを一時停止する方法を見ていて、タイマーをリセットせずに一時停止する方法がわかりません。System.Timers.Timerを一時停止する適切な方法?

一時停止の仕方は?何の一時停止はありません

+0

私は返信を見るために約1時間後に戻ってきます。 – Fredou

+0

swは_swでなければなりません。 –

+0

Pause()でIntervalを更新するかどうか分かりませんが、プライベートで値を保持することができます。 –

答えて

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 
6

は()、あなたが書くことができる1そのポーズ()上:

  1. 変更(Timeout.Infinite、Timeout.Infinite)
  2. 保存計算残りタイマーの量。再開の

():

  1. 変更(タイマーの量が残っている)

あなたはこのクラスを記述する場合、私たちの多くは、その機能を必要とするように見えるような答えでそれを投稿してくださいTimerクラスから外します。 :)

+0

私はちょうどそれをやった、あなたはどう思いますか? 1時間後に戻す – Fredou

0

あなたはShay Erlichmenの助言に従うべきです。一時停止するときの残りの時間を保存し、タイマーが再開された時点から続行する必要があります。

Me.Interval = Me.Interval - sw.ElapsedMilliseconds 

上記のコードは最初の目盛りの上に意図したとおりに、あなたが再開する次回は、それが動作することを確認して、しかしcontinouosにあなたはMe.Intervalがあるでしょうティックます:あなたの現在のコードと間違っている何のためとして、 - 元の設定間隔ではなく、間隔としてsw.ElapsedMilliseconds。

+0

サブプライベートSub ImprovedTimer_Elapsed – Fredou

-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 
+0

を無効にする/有効にすると、実際にタイマーがリセットされます。したがって、タイマー間隔が10秒で、5秒で無効にすると、有効にすると、5秒からではなく10秒から戻ってきます。 – sveilleux2

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

私はそれが少し遅れたが、いくつかのコメントを知っています。 1.マルチポーズレジュームをサポートするには、_stopWatchを追加します。開始(); _timer.Start()の後にResume()に追加します。 2. .net以前のバージョンのv4.0では、_stopWatch.Restart()を置き換えます。 _stopWatch = Stopwatch.StartNew(); 3.コンストラクタからElapsedEventHandlerを削除し、パブリックイベントElapsedEventHandler Elapsedを追加しました。 を元の動作に合わせます。 スニペットありがとうございます。 それは仕事をします。 – Tomerz

関連する問題