W aplikacji C# (.NET 4.0) używam rozszerzeń reaktywnych (2.0.20823.0) do generowania granic czasowych dla grupowania zdarzeń w wartości zagregowane. Aby uprościć zapytania do wynikowej bazy danych, granice te muszą być wyrównane do pełnych godzin (lub sekund w poniższym przykładzie).Observable.Timer(): Jak uniknąć dryfu zegara?
Korzystanie 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")));
Widać, że zamierzona i rzeczywisty czas timera kleszcze rozejścia się dość mocno:
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
...
ja również skorzystać z HistoricalScheduler
i oczywiście Nie mam żadnych problemów. Mogę tolerować niewielkie niedokładności i nie muszę przejmować się zmianami zegara systemowego. Nie ma żadnych ciężkich operacji wywołanych przez te obserwowalne.
Ponadto wiem, że istnieje długa dyskusja na temat problemów z dryftami timera RX w tym blog post, ale wydaje mi się, że nie jestem w stanie owinąć się wokół niego.
Jaki byłby właściwy sposób okresowego planowania Observable
bez systematycznego dryfowania zegara?
Wielkie dzięki, doskonała odpowiedź i wystarczająco dokładne, aby rozwiązać mój problem. Zabawnie, już to wykluczyłem, ponieważ 'Observable.Generate()' daje mi bóle głowy w [powiązanym scenariuszu] (http://stackoverflow.com/questions/13462713/why-does-observable-generate-throw- system-stackoverflowexception). Wygląda na to, że dobrze znam swój sprzęt za każdym razem, gdy zadaję pytanie związane z RX :-) –
OK, dziękuję również za wskazanie komentarzy w źródłach RX. Wygląda na to, że powinienem je częściej sprawdzać, teraz, gdy są one dostępne. –