C# Thread.Sleep(0)有什么用?

[图片] C# 异步编程_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 问题出现在视频的最后,sleep(0)和yield为什么可以发现多线程代…
关注者
65
被浏览
64,782
登录后你可以
不限量看优质回答 私信答主深度交流 精彩内容一键收藏

更新:win10 2004 版更新之后,出现很大的变化。详情看这个: Windows Timer Resolution: The Great Rule Change 更新:win10 2004 版更新之后,出现很大的变化。详情看这个:

现在我不知道怎么获得高分辨率了。

==========================================

回答这个要先从线程时间精度(时间片)开始说起。

很多参考书说,默认情况下,时间片为 15ms 左右,但是这是已经过时的知识。

在老的 Windows 操作系统里,应用程序模式时时间片 15ms 左右,准确一点是 15.625 左右。服务器模式是其双倍。

但是在微软推行.Net 普及 Task之后,规则已经改动,并且做了精细的调节。

现在Win10的时间精度为1ms(不用担心谷歌浏览器修改时间精度了),Win2013服务器的时间精度为7ms,使用 微软提供的测试工具 可以测出来。

谢谢下面评论提供的命令行: powercfg /energy

我们可以通过它可以更直观的看出:

因为有这个请求在,所以无论如何最低的计时器分辨率都只能为1ms。

所以,现在Win10 默认状态下,Sleep(1) 占时不再是15ms,而是 1ms 左右:

14167 即 1.4167ms


下面现在正式回答, Thread.Sleep(0) Thread.Yield() Thread.Sleep(1) 有什么不同:

首先, Thread.Sleep 只是放弃时间片的剩余时间,让系统重新选择调度一个合适的线程(其优先级等于或者高于当前线程)。在没有其他活动线程的情况下,使用 Sleep(0) 还是选上原来线程,即连任,如果连任了,系统不会对其做上下文切换,所以有:

其次, Thread.Yield() 是什么呢?跟 Thread.Sleep 有点像,但是它跟 Thread.Sleep(0) 有点区别:系统选择继任时可以选择优先级比原来低的线程。

最后, Thread.Sleep(1) 是什么情况呢?前面说了, Thread.Sleep 只是放弃时间片的剩余时间,让系统重新选择调度一个合适的线程。但是 Thread.Sleep(1) 却让当前线程沉睡了(即使只有 1ms )。也就是说,主动放弃下次竞选,所以不可能连任,系统上下文必然发生切换(优先级低于原线程的家伙也有机会)。

以上。


有的答主的答案是错的:


错误答案1:

Sleep(0) 不能降低CPU的占有率,只是改变了跟其他线程的占有比例, Sleep(0) 在没有其他活动线程的情况下会马上返回。



错误答案2:

这个知识点不知道从何而来,难道是更老的 Windows?


错误答案3:

如前所述,Sleep(0) 和 Yield 是有重大区别的。