C# 为什么System.Timers.Timer.Interval的数据类型是双精度的?

C# 为什么System.Timers.Timer.Interval的数据类型是双精度的?,c#,.net,timer,C#,.net,Timer,这是一个有点学术性的问题,因为我正在努力思考Microsoft使用double作为Interval属性的数据类型背后的想法 首先,从MDSN Interval开始,是以毫秒为单位的已用事件之间的时间;我认为这是一个离散的数字,为什么要使用双精度?当然int或long更有意义 间隔是否可以支持5.768585(5.768585 ms)这样的值?特别是当我们认为System.Timers.Timer的精度远低于亚毫秒时 对我来说似乎有点愚蠢。。也许我错过了什么 反汇编显示间隔是通过调用(int)Ma

这是一个有点学术性的问题,因为我正在努力思考Microsoft使用double作为Interval属性的数据类型背后的想法

首先,从MDSN Interval开始,是以毫秒为单位的已用事件之间的时间;我认为这是一个离散的数字,为什么要使用双精度?当然int或long更有意义

间隔是否可以支持5.768585(5.768585 ms)这样的值?特别是当我们认为System.Timers.Timer的精度远低于亚毫秒时


对我来说似乎有点愚蠢。。也许我错过了什么

反汇编显示间隔是通过调用
(int)Math.天花(this.interval)
消耗的,因此即使指定实数,也会在使用前将其转换为
int
。这在名为
UpdateTimer
的方法中发生

为什么??不知道,也许规范说在某一点上需要double,但这改变了吗?最终的结果是,
double
并不是严格要求的,因为它最终被转换为
int
,并且根据文档无论如何都不能大于
Int32.MaxValue

是的,计时器可以“支持”实数,它只是不告诉你它会悄悄地改变它们。您可以使用
100.5d
初始化并运行计时器,它会将计时器转换为
101


是的,这一切都有点愚蠢:4个浪费的字节,潜在的隐式转换,转换调用,显式转换,如果他们只使用了
int
,那么所有这些都是不必要的。在这里使用双精度的原因是为了提供足够的精度

详细说明:系统中断时间片由ActualResolution给出,ActualResolution由
NtQueryTimeResolution()
返回。NtQueryTimeResolution由本机Windows NT库NTDLL.DLL导出。系统时间增量由TimeIncrement给出,TimeIncrement由
GetSystemTimeAdjustment()
返回

这两个值决定系统计时器的行为。它们是整数值,表示100纳秒单位。然而,对于今天的某些硬件来说,这已经不够了。在某些系统上,实际解析返回9766,对应于0.9766毫秒。但事实上,这些系统以每秒1024次中断的速度运行(通过正确设置多媒体接口进行调整)。每秒1024次中断将导致中断周期为0.9765625 ms。这一细节太高,达到100 ps的范围,因此无法以标准实际解析格式保存

因此,决定将这些时间参数设置为双倍。但是:这并不意味着支持/使用所有可能的值。无论发生什么情况,TimeIncrement给出的粒度都将保持不变

在处理计时器时,始终建议查看所涉及参数的粒度

那么回到您的问题:
区间可以支持5.768585(ms)这样的值吗?

,我上面举的系统是不可能的

但它可以支持5.859375(毫秒)

具有不同硬件的其他系统可能支持其他号码

因此,在这里引入双重身份的想法并不是一个愚蠢的想法,实际上是有道理的。再花4个字节使事情最终正确是一项很好的投资


我总结了有关Windows时间事项的更多细节。

您尝试过吗?您是否使用过反汇编工具之一来查看如何将非整数值处理到基础Win32 API?对我来说没有多大意义。合理的选择应该是
int
TimeSpan
。@Richard,你是在含蓄地试图给我一个答案吗?我不知道我为什么要做这样的事?双重值是Win32 API上的类型约束的结果吗?我怀疑可能是这样,但我不知道(因此我不想让您找到我已经知道的答案)。更多的问题是:你有没有试着自己找出答案?我的猜测是,计时器的分辨率在未来理论上可能会提高(不到一毫秒),他们只是未来的证明。也许这只是1.1版本中的一个错误,他们没有对其进行突破性的更改,而是将其保留了下来。@ChrisSinclair可能是这样,但是当您仔细研究实现时,它会挂起
System.Threading.Timer
,而这反过来又使用了一个非托管计时器(我认为)。这一切归结为使用
uint
。所有这一切使得选择
double
的原因更加奇怪,因为基类根本不使用它。@两者:100 ns分辨率的int不能完全解析计时器功能。请看下面我的答案。虽然我不会说你说的不准确,但就
System.Timers.Timer
而言,它根本不支持
double
,因为在
Math.Ceiling
调用后,它会立即转换为
int
——在这种情况下否定了
double
的意义。@AdamHouldsworth:我并不是说所有这些实现都是正确的。同时改变一切是不可能的。因此前端(System.Timers.Timer)interval属性已收到一个合理的格式,它可能会存在很长一段时间。但是:底层软件必须正确地处理这一偏差,才能获得更好的结果。感谢您表明这还没有正确完成。因此,它需要更多的工作来纠正错误。+1为实际原因提供逻辑。这个问题是在问一个原因,而被接受的答案并没有提供一个原因。方法的实现在每次更新时都会发生变化,这可能是因为他们确实计划在将来使用lke。