gpt4 book ai didi

c# - Observable.Timer() : How to avoid timer drift?

转载 作者:可可西里 更新时间:2023-11-01 03:13:15 29 4
gpt4 key购买 nike

在 C# (.NET 4.0) 应用程序中,我使用 Reactive Extensions (2.0.20823.0) 生成时间边界以将事件分组为聚合值。为了简化对生成的数据库的查询,这些边界需要在整个小时(或下例中的秒)对齐。

使用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,当然我没有遇到任何问题。我可以容忍轻微的不准确,我不需要关心系统时钟的变化。这些 Observable 不会触发重量级操作。

此外,我知道在这个 blog post 中对 RX 计时器漂移问题进行了冗长的讨论。 ,但我似乎无法理解它。

在没有系统性计时器漂移的情况下定期安排 Observable 的正确方法是什么?

最佳答案

大多数机器上默认的 Windows 时钟中断率是每秒 64 次中断。由 CLR 四舍五入为 15.6 毫秒。如果您要求 1000 毫秒的间隔,那不是一个令人满意的数字,没有整数除数。最接近的匹配是 64 x 15.6 = 998(太短)和 65 x 15.6 = 1014 毫秒。

这正是您所看到的,41.048 - 40.034 = 1.014。 44.081 - 43.067 = 1.014,等等。

您实际上可以更改中断率,您可以调用 timeBeginPeriod() 并请求 1 毫秒的间隔。您需要在程序终止时使用 timeEndPeriod() 来重置它。这不是一件非常合理的事情,它具有系统范围的副作用并且对功耗非常不利。但会解决你的问题。

一个更明智的方法是承认你永远无法通过累加间隔来准确地计时。 CLR 使用的 15.6 毫秒已经是一个近似值。始终使用绝对时钟重新校准。通过要求 998 毫秒而不是 1000 毫秒来更接近。等等。

关于c# - Observable.Timer() : How to avoid timer drift?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13838113/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com