在会议上,有人告诉我DateTime.Now
导致IO阻塞,这是我从未停止过的事情。如果是的话,为什么?
答案 0 :(得分:5)
好吧,考虑到
使用mscorelib
上的ILSpy我们可以看到,DateTime.Now
以这种方式出现:
public static DateTime Now
{
get
{
DateTime utcNow = DateTime.UtcNow;
bool isAmbiguousDst = false;
long ticks = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousDst).Ticks;
long num = utcNow.Ticks + ticks;
if (num > 3155378975999999999L)
{
return new DateTime(3155378975999999999L, DateTimeKind.Local);
}
if (num < 0L)
{
return new DateTime(0L, DateTimeKind.Local);
}
return new DateTime(num, DateTimeKind.Local, isAmbiguousDst);
}
}
函数GetDateTimeNowUtcOffsetFromUtc
显示为:
internal static TimeSpan GetDateTimeNowUtcOffsetFromUtc(DateTime time, out bool isAmbiguousLocalDst)
{
isAmbiguousLocalDst = false;
TimeZoneInfo.OffsetAndRule oneYearLocalFromUtc = TimeZoneInfo.GetOneYearLocalFromUtc(time.Year);
TimeSpan timeSpan = oneYearLocalFromUtc.offset;
if (oneYearLocalFromUtc.rule != null)
{
bool isDaylightSavingsFromUtc = TimeZoneInfo.GetIsDaylightSavingsFromUtc(time, time.Year, oneYearLocalFromUtc.offset, oneYearLocalFromUtc.rule, out isAmbiguousLocalDst);
timeSpan += (isDaylightSavingsFromUtc ? oneYearLocalFromUtc.rule.DaylightDelta : TimeSpan.Zero);
}
return timeSpan;
}
GetOneYearLocalFromUtc
显示为:
private static TimeZoneInfo.OffsetAndRule GetOneYearLocalFromUtc(int year)
{
if (TimeZoneInfo.s_oneYearLocalFromUtc == null || TimeZoneInfo.s_oneYearLocalFromUtc.year != year)
{
TimeZoneInfo currentOneYearLocal = TimeZoneInfo.GetCurrentOneYearLocal();
TimeZoneInfo.AdjustmentRule rule = (currentOneYearLocal.m_adjustmentRules == null) ? null : currentOneYearLocal.m_adjustmentRules[0];
TimeZoneInfo.s_oneYearLocalFromUtc = new TimeZoneInfo.OffsetAndRule(year, currentOneYearLocal.BaseUtcOffset, rule);
}
return TimeZoneInfo.s_oneYearLocalFromUtc;
}
最后GetCurrentOneYearLocal
显示为:
private static TimeZoneInfo GetCurrentOneYearLocal()
{
Win32Native.TimeZoneInformation timeZoneInformation = default(Win32Native.TimeZoneInformation);
long num = (long)UnsafeNativeMethods.GetTimeZoneInformation(out timeZoneInformation);
TimeZoneInfo result;
if (num == -1L)
{
result = TimeZoneInfo.CreateCustomTimeZone("Local", TimeSpan.Zero, "Local", "Local");
}
else
{
result = TimeZoneInfo.GetLocalTimeZoneFromWin32Data(timeZoneInformation, false);
}
return result;
}
有趣的函数是GetTimeZoneInformation
,存在于kernel32.dll
中,在文档中描述如下:
检索当前时区设置。这些设置控制着 协调世界时(UTC)与当地时间之间的转换。
要访问该时间信息,Windows实际上使用IO
访问权限。不确定这个是否可以被定义为“阻塞”,但它绝对是保存在磁盘上的系统信息,至少是它的一部分。
答案 1 :(得分:4)
到目前为止,还没有人回答当前时间的真正来源。我不知道最新的PC架构。但是几年前,real-time clock是CPU(南桥)之外的芯片的一部分。因此,为了获得时间,您必须使用该芯片进行一些I / O操作。 (这不是磁盘访问,但仍然是I / O操作。)
由于当前进程必须等待来自时钟的答案,因此阻止了I / O.
所以会议上的人是对的。
答案 2 :(得分:2)
如果你使用像工具DateTime.Now调用Win API GetSystemTimeAsFileTime之类的反射器来查看源代码,之后它会使用constructor创建一个新的DateTime对象,该对象具有一个自1月1日以来带有刻度的int64参数, 0001 00:00:00.000在这里看不到任何可能导致I / O阻塞的内容,并且在GetSystemTimeAsFileTime文档中没有提到它。