• 全部
  • C#综合技术
  • C#互联网桌面应用
  • AppLauncher
  • WinForm&WPF
  • C#开发新技术
  • 问答

Thread.Sleep 的精度问题

wugamp 2017-01-19 10:56:55
我在线程中这样写:
int i=0;
while()
{
i++;
Thread.Sleep(1);
}
我们知道线程休眠的定时精度很差的,网上有说法是15ms。不论实际是多少,i 应该远远落后于实际的休眠时间。比如说当 i 为 3 时,实际休眠的时间应该已经是几十ms 了。
但是实验结果却不是这样!线程根本就没休眠,i 瞬间暴涨!(顺便祝每个回帖的人也能在2017年MONEY暴涨)
当然,如果我把1 加大,比如加到1000,那么休眠效果就出现了。
难道休眠时间太短的话就索性不休眠吗?线程调度这么聪明吗?

...全文
788 点赞 收藏 22
写回复
22 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
linzhicai656 2017-08-10
坏了,那我写的支持串口热插拔的程序 一定是假的了
回复
by_封爱 版主 2017-02-05
引用
你的DataReceived() 还在苦苦等待吗
你是听谁说的 DataReceived是"等待的"....找出原文 另外如果你发送到一半停止了..那么这条"数据"就是不合法的 在UI上面不会有任何的提示 比如超时 或者失败. 如果你不信 你可以采购一些硬件设备带"官方测试工具"那种.你可以插拔一下 看是否这样... 也就是 rx tx亮的时候 你把串口拔下去 你看UI还有反映吗...
回复
wugamp 2017-02-03
引用 19 楼 diaodiaop 的回复:
串口啊.. 根本无需sleep 那都是最原始 不知道有DataReceived的人才写出来的代码.. 因为上来的数据 是有规则的 是有协议的. 所以 你在datarec里自己累加解析就行了...
如果数据包只发了一半,后面没了,怎么办?你的 DataReceived() 还在苦苦等待吗?所以肯定需要超时判断,不要无穷等下去。可是我在这里问了这么久,没有人回答怎么实现超时判断。
回复
by_封爱 版主 2017-01-23
串口啊.. 根本无需sleep 那都是最原始 不知道有DataReceived的人才写出来的代码.. 因为上来的数据 是有规则的 是有协议的. 所以 你在datarec里自己累加解析就行了...
回复
我感觉用线程池比较好,然CPU 自己调度
回复
jwh2004 2017-01-20
和操作系统有关,不知道你用的什么系统。 如果是win7及以上系统,Thread.Sleep的最小精度可以达到1~2ms, 如果是xp系统,最小精度大约为15ms,也就是设置为1~15,效果等同于Thread.Sleep(15)
回复
wugamp 2017-01-20
引用 12 楼 shingoscar 的回复:
[quote=引用 8 楼 wugamp 的回复:] [quote=引用 6 楼 shingoscar 的回复:] 短信来了拿起手机看下就行了啊,干嘛怕它 而且串口有DataReceived事件,干嘛还怕缓冲区满了没?
但是我得知道什么时候才能去解析数据包啊。[/quote] 收到了就解析啊 解不了就先存着 反正每次DataReceived里处理就行了[/quote] 怎么判断超时??
回复
ma546515 2017-01-20
sleep不靠谱,还是用DataReceived事件来缓存数据解析,数据有明确的开始结束符或者约定
回复
卧_槽 2017-01-20
引用 2 楼 wugamp 的回复:
[quote=引用 1 楼 sp1234 的回复:] 不是聪明,是傻,好吧?!!!! 这样写 Sleep(1) 代码本来就是30年前的最傻的 c 代码的习惯。
不好,一下子被你看穿老底了! 那你说用什么办法,给点建设性意见好不好?谢谢。[/quote] 借个胖子从来只会打击人,人品忒差。
回复
卧_槽 2017-01-20
这玩意就别要求精度了。和cpu时间片相关,要是你运气不好cpu忙得要死,能差好几十秒呢。
回复
wugamp 2017-01-19
引用 3 楼 shingoscar 的回复:
这段代码未能通过编译,所以没有出现楼主说的情况
引用 3 楼 shingoscar 的回复:
这段代码未能通过编译,所以没有出现楼主说的情况
应该是 while (true) 我把 true 漏掉了。
回复
Poopaye 2017-01-19
这段代码未能通过编译,所以没有出现楼主说的情况
回复
wugamp 2017-01-19
引用 1 楼 sp1234 的回复:
不是聪明,是傻,好吧?!!!! 这样写 Sleep(1) 代码本来就是30年前的最傻的 c 代码的习惯。
不好,一下子被你看穿老底了! 那你说用什么办法,给点建设性意见好不好?谢谢。
回复
不是聪明,是傻,好吧?!!!! 这样写 Sleep(1) 代码本来就是30年前的最傻的 c 代码的习惯。
回复
Poopaye 2017-01-19
引用 8 楼 wugamp 的回复:
[quote=引用 6 楼 shingoscar 的回复:] 短信来了拿起手机看下就行了啊,干嘛怕它 而且串口有DataReceived事件,干嘛还怕缓冲区满了没?
但是我得知道什么时候才能去解析数据包啊。[/quote] 收到了就解析啊 解不了就先存着 反正每次DataReceived里处理就行了
回复
直接在DataReceived 事件里判断就好了啊,SerialPort .ReceivedBytesThreshold默认值为1,最少收到1字节就会响应这个事件
回复
wugamp 2017-01-19
引用 9 楼 zeratul1990 的回复:
来数据你就收,自己想办法解析(包头包尾?定长?),你别都在系统的缓冲区堆着啊.....
我通过长度来判断的。DataReceived 只负责把FIFO 里的东西搬到我的 byte[] 里,我的主线程反复去看 byte[]里的长度,如果长度不足就是休眠一会再来看,如果休眠了很多次还是长度不足就超时。 现在的问题就是“休眠”怎么实现。我用的是 sleep(1),被鄙视了。用 waitone,无改善。 BTW:长度有时是10,有时达到300多,变化幅度还是很大的。而且我有6个串口同时开,休眠是必须的。
回复
拜一刀 2017-01-19
来数据你就收,自己想办法解析(包头包尾?定长?),你别都在系统的缓冲区堆着啊.....
回复
wugamp 2017-01-19
引用 6 楼 shingoscar 的回复:
短信来了拿起手机看下就行了啊,干嘛怕它 而且串口有DataReceived事件,干嘛还怕缓冲区满了没?
但是我得知道什么时候才能去解析数据包啊。
回复
大宇宙尘埃 2017-01-19
根据使用环境来设置,在这里你这样设置根本就没有什么意义。你可以自己测试批量读取数据或者处理什么大批量任务时,自己观察先使用时间就知道了。
回复
相关推荐
发帖
C#
创建于2007-09-28

10.5w+

社区成员

.NET技术 C#
申请成为版主
帖子事件
创建了帖子
2017-01-19 10:56
社区公告

让您成为最强悍的C#开发者