【问题标题】:How can avoid at this line an OverflowException?如何在这一行避免溢出异常?
【发布时间】:2011-01-27 08:45:45
【问题描述】:

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

你怎么看?

【问题讨论】:

  • 在我看来,第一个选项将解决您的问题。第二个选项不会对 StackOverflow 执行任何操作,因为它会在将结果转换为 Long 之前发生。

标签: .net vb.net exception overflow casting


【解决方案1】:

假设问题如您所描述,您需要这些选项中的第一个:

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

第二个在转换为 Long 之前会失败,因为转换是在计算之后完成的。

但我认为您不应该在此计算中使用较大的负值。请注意,24.9 天后,Environment.TickCount 溢出并变为负数。也许这就是正在发生的事情?如果是这样,上面的代码不会抛出,但它会给出错误的答案。

你为什么要这样做?为什么不只比较两个 DateTime?

【讨论】:

  • 好吧,事实上这个错误是在长时间运行后发生的。我这样做是因为我使用的是 GestLastInput Windows API,它返回一个整数滴答计数,而不是日期时间。我不知道是否有更好的方法来做到这一点。
  • “长跑时间”是25天左右吗?
  • 是的,它可以运行超过 25 天。
【解决方案2】:

是的,此代码将在机器运行 2^31 毫秒后爆炸。您不能选择性地抑制 VB.NET 中的溢出检查。只有一个解决方法:项目+属性,编译选项卡,向下滚动,高级编译选项,选中“删除整数溢出检查”。这不是一个可怕的损失,但你确实失去了一定程度的保护。

另一种不会导致溢出的方法是使用 DateTime.UtcNow。减法产生一个 TimeSpan,使用它的 TotalMilliseconds 属性。准确度是一样的。注意它返回一个 Double,避免相等检查。

【讨论】:

  • 但是做演员也能避免异常不是吗?
  • 也不例外,还有一个不再起作用的计时器。你需要溢出来使它工作。
  • 是的,它会因 LastInputInfo.dwTime 而失败。使用 DateTime 不起作用,请使用“删除整数溢出检查”选项。如果您希望将代码保留在其余代码中,则可以将代码放在单独的程序集中。
  • 嗯,你能说说为什么我的最后一行行不通吗?就我所见的问题而言,它应该可以工作,因为现在您没有溢出,并且符号的更改由 Abs 处理,不是吗?在此先感谢 Nobugz,我记得您在这里和其他论坛多次帮助过我。非常感谢。
  • 插入数字。当滴答声从 +2147483647 (2^31-1, &H7fffffff) 滚动到 -2147483648 (&H80000000) 时,它会变得很糟糕。
【解决方案3】:

在 C# 中,我们只使用“未检查”块。不知道 VB.NET 中的等价物是什么。

【讨论】:

  • 据我所知这个功能在 Vb.Net 中不可用
【解决方案4】:

这就是我解决问题的方法:

            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

此代码有效,因为您获得了整数的字节,并且只是像使用 UInteger 一样使用它们,这不会引发溢出异常。

我看到的唯一问题是,当一个项目的符号发生变化时,你在做减法时有 1 个单位的错误,不确定发生了什么,但无论如何有 1 个刻度错误不是问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    相关资源
    最近更新 更多