Я предполагаю, что StartTime является положительным целым числом со знаком; Я предполагаю, что вы ранее сделали StartTime = (Environment.TickCount And Int32.MaxValue).
Abs()
не устраняет проблему. Если Interval ‹ 12,43 дня, код будет правильно определять время, пока StartTime мало. Но в некоторых случаях, всякий раз, когда StartTime > (24,86 дня — Интервал), тест будет проходить раньше, чем должен, в тот момент, когда (TickCount And Int32.MaxValue) сбрасывается до 0. Кроме того, если Interval > 12,43 дня И (TickCount А Int32.MaxValue) близко к 12,43 дня, тест никогда не пройдет.
Выполнение Environment.TickCount And Int32.MaxValue
не является необходимым и бесполезным. Он создает положительное целое число со знаком32, представляющее время в мс, которое обнуляется каждые 24,86 дня. Альтернативы сложнее понять, но они без труда позволяют вам использовать временные интервалы до 49,71 дня. Необработанный Environment.TickCount
преобразуется в Int32.MinValue через 24,86 дня и каждые 49,71 дня после этого. Приведение unchecked((Uint32)Environment.TickCount)
создает [положительное] целое число без знака 32, представляющее время в мс, которое возвращается к 0 каждые 49,71 дня. (Поскольку Environment.TickCount
вызывает функцию Windows GetTickCount(), которая возвращает DWORD (UInt32) и без проверки приводит его к Int32.)
Зацикливание Environment.TickCount
не влияет на измерение прошедшего времени. Непроверенное вычитание всегда дает правильный результат.
Вы можете вычислить прошедшее время как int32 со знаком (от -24,86 до +24,86 дней), что более полезно, если вы сравниваете независимое время или потенциально смешиваете будущее и прошлое; или unsigned int32 (от 0 до +49,71 дня). Вы можете захватить T0 как int32 со знаком или int32 без знака; это не имеет значения для результатов. Вам нужно [unchecked] приведение только в том случае, если T0 или прошедшее время не имеют знака; с подписанным T0 и подписанным прошедшим временем вам не нужны приведения.
Захват подписанного T0: (C#)
...
int iT0 = Environment.TickCount; // T0 is NOW.
...
iElapsed = unchecked(Environment.TickCount - iT0) // -24.81 to +24.81 days
uiElapsed = unchecked((uint)Environment.TickCount - (uint)iT0) // 0 to +49.71 days
if (uiElapsed >= uiTimeLimit) // IF time expired,
{
iT0 = Environment.TickCount; // For the next interval, new T0 is NOW.
...
}
Захват T0 без знака (мое предпочтение; Environment.TickCount
никогда не должно быть подписано):
...
uint uiT0 = unchecked((uint)Environment.TickCount); // T0 is NOW.
...
iElapsed = unchecked(Environment.TickCount - (int)uiT0) // -24.81 to +24.81 days
uiElapsed = unchecked((uint)Environment.TickCount - uiT0) // 0 to +49.71 days
if (uiElapsed >= uiTimeLimit) // IF time expired,
{
uiT0 = unchecked((uint)Environment.TickCount); // For the next interval, new T0 is NOW.
...
}
Если ваш TimeLimit близок к пределу цикла (24,81 или 49,71 дня), время может истечь без прохождения теста. Вы должны протестировать хотя бы один раз, пока Elapsed >= TimeLimit. (Если вы не уверены, что тестируете достаточно часто, вы можете добавить резервный тест в Elapsed. Если Elapsed когда-либо уменьшается, он завершится, поэтому время должно быть истекло.)
=====
Для временных интервалов более 49,71 дня вы можете подсчитать, сколько раз uiElapsed повторяется, или вы можете подсчитать, сколько раз Environment.TickCount
повторяется. Вы можете объединить счетчики в 64-битное значение, эмулируя GetTickCount64()
(доступно только в Windows Vista и новее). 64-битное значение имеет полный диапазон (292 миллиона лет) и полное разрешение (1 мс). Или вы можете сделать 32-битное значение с уменьшенным диапазоном и/или разрешением. Код, проверяющий перенос, должен выполняться не реже одного раза в 49,71 дня, чтобы убедиться, что перенос не обнаружен.
uint uiTickCountPrev = 0;
uint uiTickWrap = 0;
Int64 TickCount64;
...
uiTickCount = unchecked((uint)Environment.TickCount) // 0 to +49.71 days
if (uiTickCount < uiTickCountPrev) // IF uiElapsed decreased,
uiWrapcount++; count that uiElapsed wrapped.
uiElapsedPrev = uiElapsed; // Save the previous value.
TickCount64 = (Int64)uiTickWrap << 32 + (Int64)uiTickCount;
Заметки:
Environment.TickCount
указывает время с момента загрузки в мс с разрешением 10-16 мс.
Непроверенная разница Int32 дает разницу во времени от -24,81 до +24,81 дня с циклическим циклом. Непроверенное вычитание 32-битных целых чисел приводит к переполнению и циклическому переходу к правильному значению. Знак Environment.TickCount
никогда не имеет значения. Пример, перенос на единицу: iBase = Environment.TickCount
получает Int32.MaxValue
; через один тик Environment.TickCount
заменяется на Int32.MinValue
; и unchecked(Environment.TickCount - iBase)
дает 1.
Непроверенная разница UInt32 дает разницу во времени от 0 до +49,71 дня с циклическим циклом. (Прошедшее время никогда не может быть отрицательным, так что это лучший выбор.) Неконтролируемое вычитание 32-битных целых чисел без знака переполняется и возвращается к правильному значению. Пример, перенос на единицу: iBase = Environment.TickCount
получает UInt32.MaxValue
; через один тик Environment.TickCount
заменяется на UInt32.MinValue
; и unchecked(Environment.TickCount - iBase)
дает 1.
person
A876
schedule
24.10.2016