DateTime.Now导致IO阻塞?

时间:2012-06-05 14:58:46

标签: c#

在会议上,有人告诉我DateTime.Now导致IO阻塞,这是我从未停止过的事情。如果是的话,为什么?

3 个答案:

答案 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文档中没有提到它。