より正確なタイマーを!
結構遅れるTask.Delay
メソッド
時間待ちにTask.Delay
メソッドを使うと、どうも指定した時間より数十ミリ秒長く待っているようです。
(前回のコードでは、AutoResetEvent.WaitOne
/ManualResetEvent.WaitOne
メソッドを使っていますが、たぶん同じように遅れますね)
Task.Delay
の呼び出しの間にSense HATに対するI/Oをしていますので、I/Oが遅いのかもしれません。
あるいは、そもそもRaspberry PiかWindows 10 IoTの、タイマー分解能の限界かもしれません。
どちらが原因にせよ、繰り返し時間待ちがあると誤差が降り積もって、どんどん遅れてしまいます!
より正確な時間待ち!
ということで、より正確に繰り返し時間待ちができるクラスを作ってみました。
using System; using System.Threading.Tasks; // 待ち時間を指定して繰り返し待つためのタイマー internal class IntervalTimer { // 時間待ち明けの予定時刻 private DateTime BaseTime { get; set; } // コンストラクター public IntervalTimer() => Reset(); // 時間待ち明けの予定時刻を現在時刻にセットしなおす public void Reset() => BaseTime = DateTime.Now; // 引数で指定した時間、待つ public async Task Delay(TimeSpan timeSpan) { // 時間待ち明けの予定時刻との差を引数から減じ、待ち時間を求める TimeSpan diff = timeSpan - (DateTime.Now - BaseTime); // 時間待ち明けの予定時刻をセットする BaseTime += timeSpan; // 待つ if (diff > TimeSpan.Zero) await Task.Delay(diff); } }
このクラスのインスタンスを作り、Task.Delay
メソッドの代わりにIntervalTimer.Delay
を呼び出して、時間待ちします。
個々の時間待ちは依然として遅れますが、遅れが降り積もっていくことは避けられます!
いろいろ難しい!