我知道它DateTime.UtcNow
没有相对较高的精度(10-15 ms 分辨率)。
这对我来说是个问题,因为在我的日志文件中,我想要更好的分辨率来解决竞争条件。
问题是:我怎样才能以比DateTime.UtcNow
提供的更好的精度获得当前日期/时间?
到目前为止,我看到的唯一解决方案是:https ://stackoverflow.com/a/15008836/270348 。这是解决问题的合适方法吗?
您可以使用Stopwatch
更精确的时间测量。然后,您可以让每个日志条目记录从第一个操作开始的时间。如果这很重要,您可以记录DateTime
第一个操作的时间,从而计算其余的时间,但听起来只有第一个操作开始以来的滴答声/纳秒就足以满足您的目的。
如果您想添加跟踪,您可以像这里一样编写自己的 ETW 跟踪提供程序。然后你不需要关心如何获取时间。Windows 内核将确保时间准确且事件顺序正确。
如果您不想编写自己的 ETW 提供程序,您可以使用作为 Nuget 包提供的 EventSource,它也允许您从 .NET 4.0 使用它。更多信息有Vance Morrison在他的博客上。
使用 ETW 事件时,您可以通过 Windows 性能工具包免费获得功能强大的跟踪分析器。作为额外的好处,您可以在所有进程中进行系统范围的分析,并且影响最小。
这允许您有选择地为您编写的每个事件添加调用堆栈,这在您想要跟踪谁确实调用了您的 Dispose 方法两次时非常有用。
您真的需要一个精确的计时器,还是您真正需要的是可以提供某种功能的东西?例如:
static class AutoIncrement
{
private static long num;
public static long Current
{
get
{
return Interlocked.Increment(ref num);
}
}
}
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
这保证是唯一的,并且每次都改变,并且被排序。它的精度优于微秒。它的精度在单台 PC 上是绝对的。
或者如果你真的想要时间戳......
static class AutoIncrement
{
private static long lastDate;
public static DateTime Current
{
get
{
long lastDateOrig, lastDateNew;
do
{
lastDateOrig = lastDate;
lastDateNew = lastDateOrig + 1;
lastDateNew = Math.Max(DateTime.UtcNow.Ticks, lastDateNew);
}
while (Interlocked.CompareExchange(ref lastDate, lastDateNew, lastDateOrig) != lastDateOrig);
return new DateTime(lastDateNew, DateTimeKind.Utc);
}
}
}
DateTime ac = AutoIncrement.Current;
Console.WriteLine(CultureInfo.InvariantCulture, "{0} {1:yyyy/MM/dd HH:mm:ss.fffffff}", ac.Ticks, ac);
最后一个变体用作 base DateTime.UtcNow
,但每次调用如果未更改,则将其递增一。