毫秒精度的 Windows 系统时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3140826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Windows system time with millisecond precision
提问by Badr
Related to my previous question, but with C#, I need the precise system time including milliseconds.
与我之前的问题相关,但使用 C#,我需要精确的系统时间,包括毫秒。
C# time function has accuracy up to 10 to 15 milliseconds, but not exactly 1 millisecond.
C# 时间函数的精度可达 10 到 15 毫秒,但不完全是 1 毫秒。
The same is the case with Queue performance counter. Is there any other way to get accuracy up to exact millisecond?
队列性能计数器的情况也是如此。有没有其他方法可以将准确度提高到精确到毫秒?
回答by Dan Herbert
You could use this DateTimePrecise classto get a high accuracy time in .NET
您可以使用此 DateTimePrecise 类在 .NET 中获得高精度时间
UPDATE
The CodeProject link is no longer working. I've pulled the code from archive.organd embedded it here for future reference. This code is included here "as is", exactly the way it was included on the CodeProject page.
更新
CodeProject 链接不再有效。我已经从 archive.org 中提取了代码并将其嵌入此处以供将来参考。此代码“按原样”包含在此处,与包含在 CodeProject 页面上的方式完全相同。
DateTimePrecise
is as easy to use asDateTime.Now
, except thatDateTimePrecise.Now
is an instance method instead of a static method, so you have to first instantiate aDateTimePrecise
.
DateTimePrecise
和 一样容易使用DateTime.Now
,只是它DateTimePrecise.Now
是一个实例方法而不是静态方法,所以你必须先实例化一个DateTimePrecise
.
using System.Diagnostics;
/// DateTimePrecise provides a way to get a DateTime that exhibits the
/// relative precision of
/// System.Diagnostics.Stopwatch, and the absolute accuracy of DateTime.Now.
public class DateTimePrecise
{
/// Creates a new instance of DateTimePrecise.
/// A large value of synchronizePeriodSeconds may cause arithmetic overthrow
/// exceptions to be thrown. A small value may cause the time to be unstable.
/// A good value is 10.
/// synchronizePeriodSeconds = The number of seconds after which the
/// DateTimePrecise will synchronize itself with the system clock.
public DateTimePrecise(long synchronizePeriodSeconds)
{
Stopwatch = Stopwatch.StartNew();
this.Stopwatch.Start();
DateTime t = DateTime.UtcNow;
_immutable = new DateTimePreciseSafeImmutable(t, t, Stopwatch.ElapsedTicks,
Stopwatch.Frequency);
_synchronizePeriodSeconds = synchronizePeriodSeconds;
_synchronizePeriodStopwatchTicks = synchronizePeriodSeconds *
Stopwatch.Frequency;
_synchronizePeriodClockTicks = synchronizePeriodSeconds *
_clockTickFrequency;
}
/// Returns the current date and time, just like DateTime.UtcNow.
public DateTime UtcNow
{
get
{
long s = this.Stopwatch.ElapsedTicks;
DateTimePreciseSafeImmutable immutable = _immutable;
if (s < immutable._s_observed + _synchronizePeriodStopwatchTicks)
{
return immutable._t_base.AddTicks(((
s - immutable._s_observed) * _clockTickFrequency) / (
immutable._stopWatchFrequency));
}
else
{
DateTime t = DateTime.UtcNow;
DateTime t_base_new = immutable._t_base.AddTicks(((
s - immutable._s_observed) * _clockTickFrequency) / (
immutable._stopWatchFrequency));
_immutable = new DateTimePreciseSafeImmutable(
t,
t_base_new,
s,
((s - immutable._s_observed) * _clockTickFrequency * 2)
/
(t.Ticks - immutable._t_observed.Ticks + t.Ticks +
t.Ticks - t_base_new.Ticks - immutable._t_observed.Ticks)
);
return t_base_new;
}
}
}
/// Returns the current date and time, just like DateTime.Now.
public DateTime Now
{
get
{
return this.UtcNow.ToLocalTime();
}
}
/// The internal System.Diagnostics.Stopwatch used by this instance.
public Stopwatch Stopwatch;
private long _synchronizePeriodStopwatchTicks;
private long _synchronizePeriodSeconds;
private long _synchronizePeriodClockTicks;
private const long _clockTickFrequency = 10000000;
private DateTimePreciseSafeImmutable _immutable;
}
internal sealed class DateTimePreciseSafeImmutable
{
internal DateTimePreciseSafeImmutable(DateTime t_observed, DateTime t_base,
long s_observed, long stopWatchFrequency)
{
_t_observed = t_observed;
_t_base = t_base;
_s_observed = s_observed;
_stopWatchFrequency = stopWatchFrequency;
}
internal readonly DateTime _t_observed;
internal readonly DateTime _t_base;
internal readonly long _s_observed;
internal readonly long _stopWatchFrequency;
}
回答by Gabe
Windows does not want to waste electricity by updating the system clock 1000 times per second, so the default is to only update it 60-100 times per second. If you set the multimedia timer to 1ms, you can get 1ms resolution from the clock, but that's not recommended.
Windows 不想通过每秒更新 1000 次系统时钟来浪费电力,因此默认为每秒仅更新 60-100 次。如果您将多媒体计时器设置为 1ms,则可以从时钟获得 1ms 的分辨率,但不建议这样做。
To elaborate more on the electricity savings, what happens when the CPU is idle for a period of time is that it can go into a very-low-power state. Whenever it gets interrupted (e.g. to increment the clock ticks) it has to leave its very-low-power state and use lots of electricity to power the whole CPU to service that interrupt. In other words, the additional power isn't in incrementing the clock ticks, it's in keeping the CPU awake to do it.
为了更详细地说明节电,当 CPU 空闲一段时间时会发生什么,它可以进入一个非常低功耗的状态。每当它被中断(例如增加时钟滴答)时,它必须离开其极低功耗状态并使用大量电力为整个 CPU 供电以服务该中断。换句话说,额外的功率不是增加时钟滴答声,而是保持 CPU 清醒来做到这一点。
Since my laptop uses 10W at idle when the clock frequency is 60Hz and 11W when it's 1000Hz, and I get 300 minutes of battery life, that slower clock is giving me almost 30 extra minutes of battery life!
由于我的笔记本电脑在时钟频率为 60Hz 时闲置时使用 10W,在时钟频率为 1000Hz 时使用 11W,而且我的电池续航时间为 300 分钟,因此较慢的时钟为我提供了近 30 分钟的电池续航时间!
回答by xcud
Try System.Diagnostics.Stopwatchfor high-resolution timing.
尝试System.Diagnostics.Stopwatch以获得高分辨率计时。
If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time. Otherwise, the Stopwatch class uses the system timer to measure elapsed time.
如果安装的硬件和操作系统支持高分辨率性能计数器,则 Stopwatch 类使用该计数器来测量经过的时间。否则,秒表类使用系统计时器来测量经过的时间。
Try the native DateTime.Ticksfor system time accuracy up to one hundred nanoseconds; 1 millisecond = 10000 ticks.
尝试使用原生DateTime.Ticks将系统时间精度提高到 100 纳秒;1 毫秒 = 10000 个滴答声。
while (true)
{
System.Threading.Thread.Sleep(1);
Console.WriteLine("{0} {1}",
System.DateTime.Now.Ticks,
System.DateTime.Now.ToString("ss:fff"));
}
PS > .\test.exe
634134152924322129 52:432
634134152924332129 52:433
634134152924342130 52:434
634134152924352130 52:435
634134152924362131 52:436
634134152924372131 52:437
634134152924382132 52:438
634134152924392133 52:439
634134152924402133 52:440
634134152924412134 52:441
634134152924422134 52:442
634134152924432135 52:443