C#(.NET 4.0)アプリケーションでは、Reactive Extensions(2.0.20823.0)を使用して、イベントを集計値にグループ化するための時間境界を生成します。結果のデータベースへのクエリを単純化するには、これらの境界を1時間(または以下の例では秒)に揃える必要があります。
使用Observable.Timer()
:
var time = DefaultScheduler.Instance;
var start = new DateTimeOffset(time.Now.DateTime, time.Now.Offset);
var span = TimeSpan.FromSeconds(1);
start -= TimeSpan.FromTicks(start.Ticks % 10000000);
start += span;
var boundary = Observable.Timer(start, span, time);
boundary.Select(i => start + TimeSpan.FromSeconds(i * span.TotalSeconds))
.Subscribe(t => Console.WriteLine("ideal: " + t.ToString("HH:mm:ss.fff")));
boundary.Select(i => time.Now)
.Subscribe(t => Console.WriteLine("actual: " + t.ToString("HH:mm:ss.fff")));
タイマーティックの意図された時間と実際の時間がかなり大きくずれていることがわかります。
ideal: 10:06:40.000
actual: 10:06:40.034
actual: 10:06:41.048
ideal: 10:06:41.000
actual: 10:06:42.055
ideal: 10:06:42.000
ideal: 10:06:43.000
actual: 10:06:43.067
actual: 10:06:44.081
ideal: 10:06:44.000
ideal: 10:06:45.000
actual: 10:06:45.095
actual: 10:06:46.109
ideal: 10:06:46.000
ideal: 10:06:47.000
actual: 10:06:47.123
actual: 10:06:48.137
ideal: 10:06:48.000
...
私も利用していHistoricalScheduler
て、もちろん問題ありません。わずかな不正確さは許容でき、システムクロックの変更を気にする必要はありません。これらのオブザーバブルによってトリガーされる重い操作はありません。
また、このブログ投稿でRXタイマーのドリフトの問題について長い議論があることは知っていますが、頭を悩ませることはできないようです。
Observable
体系的なタイマードリフトなしで定期的にスケジュールする正しい方法は何でしょうか?