我知道DateTime.UtcNow
没有相对较高的精确度(10-15 ms分辨率)。
这对我来说是一个问题,因为在我的日志文件中,为了解决竞争条件,我想要更好的分辨率。
问题是:如何以比DateTime.UtcNow
提供的更精确的方式获得当前日期/时间?
到目前为止,我见过的唯一解决方案是:https://stackoverflow.com/a/15008836/270348。这是解决问题的合适方法吗?
答案 0 :(得分:9)
您可以使用Stopwatch
进行更精确的时间测量。然后,您可以让每个日志条目记录从第一个操作开始的时间。如果它很重要,你可以记录第一个操作的DateTime
,从而计算剩下的时间,但是听起来就像是第一个操作开始后的滴答/纳秒就足够了。
答案 1 :(得分:4)
如果要添加跟踪,可以编写自己的ETW跟踪提供程序,如here。那么你不需要注意如何获取时间。 Windows内核会关注时间是否准确以及事件的顺序是否正确。
如果您不想编写自己的ETW提供程序,可以使用可用作Nuget Package的EventSource,它允许您在.NET 4.0中使用它。更多信息在他的博客上有Vance Morrison。
使用ETW事件时,您可以使用Windows Performance Toolkit免费获得功能强大的跟踪分析器。作为额外的奖励,您可以在所有流程中进行系统范围的分析,同时影响最小。
这允许您有选择地为您编写的每个事件添加调用堆栈,当您想要追踪谁调用您的Dispose方法两次时,这可能是非常宝贵的。
答案 2 :(得分:2)
你真的需要一个精确的计时器,或者你真正需要的东西是什么?例如:
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);
最后一个变体用作基础DateTime.UtcNow
,但每次调用如果没有更改,则将其递增1。