Thread.Sleep(0):什么是正常的行为?

为了理解Thread.Sleep(0)在OS上强制上下文切换。

我想查看在接收一些CPU时间之前可以传递给应用程序的最大时间。

所以我构build了一个在while循环(c#)中执行Thread.Sleep(0)的应用程序,并计算每次调用之间传递的时间。

当这个应用程序是唯一在双核心testingPC上运行的应用程序时,最大观察时间正好在1毫秒(平均为0.9微秒),它使用所有可用的CPU(100%)。

当我沿着CPU填充虚拟应用程序(全部具有相同的优先级)运行它时,最大时间约为25ms,平均时间为20ms。 它的行为完全如我所料。 时间非常稳定。

每当CPU获得一些CPU时间时,立即将控制权交还给需要处理的人,这就像热土豆游戏(CPU使用率下降到0%)。 如果没有其他应用程序正在运行,则控件立即返回。

鉴于此行为,我预计此应用程序对运行实际应用程序的计算机具有最小的影响。 (并给我实际的“延迟”,我期望看到在那里运行的应用程序)。 但令我惊讶的是,这确实影响了(以可观察的方式)这个特定系统的performance。

我是否错过了有关Thread.Sleep(0)的一些重要观点?

作为参考这里是这个应用程序的代码

private bool _running = true; private readonly Stopwatch _timer = new Stopwatch(); private double _maxTime; private long _count; private double _average; private double _current; public Form1() { InitializeComponent(); Thread t = new Thread(Run); t.Start(); } public void Run() { while(_running) { _timer.Start(); Thread.Sleep(0); _timer.Stop(); _current = _timer.Elapsed.TotalMilliseconds; _timer.Reset(); _count++; _average = _average*((_count - 1.0)/_count) + _current*(1.0/_count); if(_current>_maxTime) { _maxTime = _current; } } } 

为清晰起见(应用程序的目的)进行了编辑:目前我正在运行一个软实时multithreading应用程序(以及一组应用程序),需要每隔大约300ms对某些input做出反应,但我们确实会错过一些不定期的时间(less于1%的时间),我正在努力改善这个数字。

我想validation在同一台机器上由其他进程引起的当前可变性是什么:通过将上面写在这个半实时机器上的应用程序拟合,所观察到的最大时间将告诉我系统引起什么变化。 IE我有300毫秒,但最大观察时间线程得到一些CPU时间之前站在50毫秒,所以为了提高性能,我应该设置我的处理时间最多250毫秒(因为我可能已经是50毫秒晚)。

Solutions Collecting From Web of "Thread.Sleep(0):什么是正常的行为?"

它不强制上下文切换,只有睡眠(1)这样做。 但是,如果有任何其他线程从任何进程准备好运行,并具有更高的优先级,然后睡眠(0)将产生处理器,让它运行。 你可以通过运行一个叫做Sleep(0)的无限循环来看到这一点,它将在一个内核上100%的CPU周期。 我不明白你为什么不观察这种行为。

保持系统响应的最好方法是给你的线程一个低优先级。

在之前的项目中,我被这个bug咬了一口。 我有一个线程运行,将检查优先级队列中的消息,寻找一个新的。 如果没有发现新消息,我希望线程进入休眠状态,直到消息被添加到队列中,然后将其唤醒以再次检查。

天真地说,假设Thread.Sleep(0)会导致线程进入休眠状态,直到再次唤醒,我发现我们的应用程序一旦消息进入就消耗疯狂的CPU数量。

经过几天的调查可能的原因,我们发现这个链接的信息。 快速修复是使用Thread.Sleep(1) 链接有详细的差异原因,包括底部的一个小测试应用程序,展示了两个选项之间的性能会发生什么。

最可能的原因是您不允许程序以有效的方式阅读说明。

当您调用Sleep(0)您的代码暂停一个周期,然后计划下一个可用的插槽。 但是,这种上下文切换不是免费的 – 有很多寄存器可以保存/加载,而且当你有不同的指令序列从磁盘读取时,最终可能会导致很多缓存未命中。 在大多数情况下,我无法想象这会对您的应用程序产生重大影响,但如果您正在使用实时系统或类似的密集型应用程序,那么这可能是一种可能性。

我的理解是,Thread.Sleep(0)不强制线程上下文切换,它只是告诉任务调度程序,如果有其他线程在等待执行,您愿意放弃时间片的其余部分。

围绕睡眠(0)的循环正在咀嚼CPU时间,这将对其他应用程序(以及笔记本电脑的电池寿命)产生负面影响。 睡眠(0)并不意味着“让所有的东西都先执行”,所以你的循环将与其他进程竞争执行时间。

将一个非零的等待时间传递给Sleep()对于其他应用程序来说稍微好一点,因为它实际上会迫使这个线程被搁置一段时间。 但是,这仍然不是如何实现影响最小的后台线程。

运行CPU绑定后台线程对前台应用程序影响最小的最佳方法是将线程优先级降至低于正常水平。 这将告诉调度程序首先执行所有普通优先级线程,如果/有任何其他时间可用,则执行您的低优先级线程。 这样做的副作用是,根据CPU的饱和程度,有时你的低优先级的线程可能根本不会得到相对较长的时间(秒)的执行时间。

我怀疑你注意到由于你的其他程序的影响也只有CPU绑定。 因此,这也是第三个运行你没有考虑OS调度器的程序。

非受影响的程序被操作系统阻止,以允许程序运行,并有上下文命中来交换进程,然后加载你的程序,然后再次卸载它。