Как можно избежать в этой строке OverflowException? - PullRequest
0 голосов
/ 14 марта 2010

LastInput.time является целым числом, а m_idleTime также является целым числом. Эта строка иногда генерирует исключение переполнения, я думаю, что это происходит, когда оба значения большие отрицательные значения.

(Environment.TickCount - lastInput.time) > m_idleTime

Как мне этого избежать? С литья?

(CType(Environment.TickCount,Long) - CType(lastInput.time,Long)) > m_idleTime

Или, может быть, с этим составом?

CType((Environment.TickCount - lastInput.time),Long) > m_idleTime

Заранее спасибо.

РЕДАКТИРОВАТЬ: я использую метод GetLastInputInfo, чтобы проверить, сколько раз компьютер простаивал. Я объявил возвращаемое значение из вызова следующим образом:

    <StructLayout(LayoutKind.Sequential)> Public Structure StructLastInputInfo
        <MarshalAs(UnmanagedType.U4)> Dim size As Integer
        <MarshalAs(UnmanagedType.U4)> Dim time As Integer
    End Structure

Так что я думаю, что когда Environment.TickCount возвращает отрицательное значение, то же самое произойдет и с GetLastInputInfo, верно? Но тогда значения вычитания будут неправильными, потому что они будут отрицательными, так что, насколько я понимаю, проблема заключается в следующем:

Math.Abs(CType(Environment.TickCount, Long) - CType(lastInput.time, Long)) > m_idleTime

Что вы думаете?

Ответы [ 4 ]

1 голос
/ 14 марта 2010

Да, этот код будет бомбить после того, как машина будет работать в течение 2 ^ 31 миллисекунд. Вы не можете выборочно подавлять проверку переполнения в VB.NET. Для этого есть только одно исправление: Project + Properties, вкладка Compile, прокрутка вниз, Advanced Compile Options, проверка «Удалить проверки целочисленного переполнения». Это не страшная потеря, но вы теряете уровень защиты.

Другим способом, который не вызывает переполнения, является использование DateTime.UtcNow. Вычитание создает TimeSpan, используйте его свойство TotalMilliseconds. Точность такая же. Остерегайтесь того, что он возвращает Double, избегайте проверок на равенство.

1 голос
/ 14 марта 2010

Если проблема в том, что вы описали, вам нужен первый из этих вариантов:

(CType(Environment.TickCount,Long) - CType(lastInput.time,Long)) > m_idleTime

Второй произойдет сбой, прежде чем он преобразуется в Long, потому что преобразование выполняется после вычисления.

Но я бы подумал, что в этом расчете не должно быть больших отрицательных значений. Обратите внимание, что через 24,9 дня Environment.TickCount переполняется и становится отрицательным. Может быть, это то, что происходит? Если это так, приведенный выше код не будет выдан, но даст неправильный ответ.

Почему ты так делаешь? Почему бы просто не сравнить два DateTimes?

0 голосов
/ 16 марта 2010

Вот как я исправил проблему:

            currentTime = BitConverter.ToUInt32(BitConverter.GetBytes(Environment.TickCount), 0) #'' This code can fail with 1 tick error when changing the sign of one item.
            lastInputTime = BitConverter.ToUInt32(BitConverter.GetBytes(lastInput.time), 0)

            If currentTime - lastInputTime > m_idleTime Then

Этот код работает, потому что вы получаете байты Integer и просто используете их, как если бы они были UInteger, это не выдает OverflowException.

Единственная проблема, которую я видел, состоит в том, что у вас возникает ошибка в 1 единицу при выполнении вычитания, когда знак одного элемента изменился, не уверен в том, что происходит, но в любом случае наличие ошибки в 1 такт не является проблемой.

0 голосов
/ 14 марта 2010

В C # мы просто используем «непроверенный» блок. Не уверен, что эквивалентно в VB.NET.

...