带符号/无符号整数位移代码解析及Thread.Sleep异常原因咨询
代码逻辑解析与异常原因说明
一、代码逻辑拆解
先贴出修正了大小写问题的代码(原代码toArray()应为ToArray(),C#方法名遵循帕斯卡命名法):
using (MemoryStream mem = new MemoryStream(bytes.Skip(4).ToArray())) { using (BinaryReader reader = new BinaryReader(mem)) { UInt32 time1; UInt32 time2; Int64 time = 0; try { time1 = reader.ReadInt32(); time2 = reader.ReadInt32(); time = (((Int64)time2) << 32) | time1; return new DateTime(time); } catch { } } }
这段代码的核心是从字节数组中解析时间戳并转换为DateTime对象,具体步骤如下:
- 跳过无效前缀:通过
bytes.Skip(4).ToArray()丢弃字节数组前4个字节,将剩余内容存入MemoryStream作为读取数据源。 - 读取高低位整数:用
BinaryReader读取两个32位整数,分别存入time1(低32位)和time2(高32位)。这里用ReadInt32()读带符号整数却赋值给无符号UInt32,本质是直接读取二进制位,不做符号转换。 - 拼接64位时间值:把
time2强制转为Int64后左移32位(腾出低32位空间),再和time1做按位或运算,将两个32位值拼接成完整的64位整数time。 - 转换为DateTime:
DateTime构造函数接受的Int64参数代表从0001年1月1日00:00:00起的100纳秒间隔数(Ticks),这段代码就是把拼接后的64位值当作Ticks生成时间对象。 - 静默吞掉异常:空
catch块会处理所有异常(比如字节数组剩余长度不足8字节、读取失败等),但这种写法会掩盖问题,不利于调试。
二、Thread.Sleep调用时的异常原因
Thread.Sleep的参数规则很明确:只能接受非负整数(0到Int32.MaxValue,即2147483647毫秒,约24.8天)或者-1(部分环境支持无限等待),超出范围就会抛出你看到的OutOfRange异常。
出现问题的核心是传给Thread.Sleep的参数不符合要求,常见场景有两种:
- 参数为负数:比如你用当前时间减去这段代码返回的
DateTime得到TimeSpan,如果返回的时间比当前时间晚,TimeSpan.TotalMilliseconds会是负数,直接传给Thread.Sleep就会触发异常(仅-1是允许的负数)。 - 参数超出Int32最大值:如果直接把
DateTime.Ticks转成毫秒传给Thread.Sleep,Ticks的值通常在10^17级别,远大于Int32.MaxValue;或者计算出的等待时间超过24.8天,也会触发异常。
补充:原代码用ReadInt32()给UInt32赋值存在风险,如果原始数据是无符号32位整数,应该用ReadUInt32()更准确,避免带符号转无符号时的意外值。
内容的提问来源于stack exchange,提问作者duk3th3c0d3r
相关产品推荐
相关产品推荐

