Вопрос по c# – DateTime.Now вызывает блокировку ввода-вывода?
На конференции кто-то сказал мне, чтоDateTime.Now
вызывает блокировку ввода-вывода, что я никогда не переставал рассматривать. Если это так, почему?
Ну, учитывая что
с помощьюILSpy наmscorelib
мы можем выяснить, что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
который описан в документации как:
Retrieves the current time zone settings. These settings control the translations between Coordinated Universal Time (UTC) and local time.
Для доступа к информации о времени Windows фактически используетIO
доступ. Не уверен, что этоcan быть определенным как «блокирование», но это определенно влияет на системную информацию, сохраненную на диске, по крайней мере, на его части.
Если вы посмотрите на источник с каким-то отражателем, подобным инструменту DateTime.Now, вызовите Win APIGetSystemTimeAsFileTime и после этого он создает новый объект DateTime, используяконструктор которые имеют один параметр int64 с тиками с 1 января 0001 в 00: 00: 00.000. Здесь не видно ничего, что могло бы вызвать блокировку ввода-вывода, и об этом нет упоминания в документации GetSystemTimeAsFileTime.
Никто до сих пор не ответил, откуда на самом деле исходит текущее время. Я не в курсе новейшей архитектуры ПК. Но несколько лет назадчасы реального времени был частью микросхемы вне процессора (южный мост). Таким образом, чтобы получить время, вы должны были выполнить некоторые операции ввода-вывода с этим чипом. (Это не доступ к диску, а операция ввода-вывода.)
И поскольку текущий процесс должен ждать ответа от часов, он блокирует ввод / вывод.
Так что этот человек на конференции был прав.