Я предполагаю, что StartTime является целым положительным знаком; Я предполагаю, что вы ранее сделали StartTime = (Environment.TickCount And Int32.MaxValue).
Abs()
не не решает проблему. Если интервал <12,43 дней, код будет корректно рассчитываться, пока StartTime невелик. Но иногда, когда StartTime> (24,86 дней - интервал), тест проходит раньше, чем должен, в тот момент, когда (TickCount And Int32.MaxValue) переходит на 0. Кроме того, если Interval> 12,43 дней AND (TickCount) И Int32.MaxValue) близко к 12,43 дням, тест никогда не пройдет.
Делать Environment.TickCount And Int32.MaxValue
не нужно и не полезно. Он создает целое число с положительной подписью, представляющее время в мс, которое оборачивается до 0 каждые 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 дней), что более полезно, если вы сравниваете независимое время или потенциально смешиваете будущее и прошлое; или без знака 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.