Я создал таймер с паузой, используя как System.Timers.Timer
, так и System.Diagnostics.Stopwatch
, следующим образом:
public class PausableTimer
{
private double interval;
private readonly Timer timer;
private readonly Stopwatch stopwatch;
public event ElapsedEventHandler Tick
{
add => timer.Elapsed += value;
remove => timer.Elapsed -= value;
}
public int Interval
{
get => Convert.ToInt32(timer.Interval);
set
{
if (Enabled)
{
throw new Exception("Can't set interval while running");
}
else
{
interval = Convert.ToDouble(value);
SetInterval(value);
}
}
}
public bool Enabled
{
get => timer.Enabled;
set
{
if (value)
{
Start();
}
else
{
Stop();
}
}
}
public double Elapsed
{
get => stopwatch.Elapsed.TotalMilliseconds;
}
public PausableTimer(int milliseconds)
{
interval = Convert.ToInt32(milliseconds);
stopwatch = new Stopwatch();
timer = new Timer(interval);
timer.AutoReset = true;
timer.Elapsed += OnElapsed;
}
private void OnElapsed(object sender, ElapsedEventArgs e)
{
lock (this)
{
stopwatch.Reset();
SetInterval(interval);
stopwatch.Start();
}
}
public void Start()
{
lock (this)
{
stopwatch.Reset();
timer.Start();
stopwatch.Start();
}
}
public void Stop()
{
lock (this)
{
timer.Stop();
stopwatch.Stop();
}
}
public void Pause()
{
lock (this)
{
Stop();
SetInterval(Interval - stopwatch.Elapsed.TotalMilliseconds);
}
}
private void SetInterval(double value)
{
timer.Interval = Math.Max(value, 0.1);
}
}
Все казалось правильным, пока я не начал писать несколько тестовых примеров и не обнаружил, что следующий код выдает странные результаты:
new TaskFactory().StartNew(() =>
{
var stopwatch = new Stopwatch();
var interval = 32;
stopwatch.Start();
Thread.Sleep(interval);
stopwatch.Stop();
Console.WriteLine("Elapsed: {0}. Expected: {1}.", stopwatch.Elapsed.TotalMilliseconds, interval);
});
Последние 5 результатов (stopwatch.Elapsed.TotalMilliseconds
):
- 57.1516
- 57.4105
- 60.5827
- 43.0608
- 52.7358
Это огромная разница. Почему эти значения не близки к 32
?
Это влияет на мои результаты класса PausableTimer
.
PausableTimer
с точки зрения точности. - person Yves Calaci   schedule 14.04.2021PausableTimer
так же неточно, как, например,System.Timers.Timer
? Это оно? - person Yves Calaci   schedule 14.04.2021var duration = new Subject<TimeSpan>(); var pausableTimer = duration.Select(x => x == TimeSpan.Zero ? Observable.Never<long>() : Observable.Interval(x)).Switch();
- person Enigmativity   schedule 14.04.2021