c# - 为什么 Thread.Sleep 在其他应用程序运行时等待的时间比请求的时间长?

标签 c# .net multithreading behavior

我有一个关于 C# 线程的小问题。 出于某种原因,当我打开 Chrome 时,我的线程从 32 毫秒延迟加速到 16 毫秒延迟,当我关闭 Chrome 时,它​​又回到 32 毫秒。我正在使用 Thread.Sleep(1000/60) 来延迟。 有人可以解释为什么会发生这种情况,并可能提出一个可能的解决方案吗?

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading;

 namespace ConsoleApplication2
 {
     class Program
     {
         static bool alive;
         static Thread thread;
         static DateTime last;

         static void Main(string[] args)
         {
             alive = true;
             thread = new Thread(new ThreadStart(Loop));
             thread.Start();

             Console.ReadKey();
         }

         static void Loop()
         {
             last = DateTime.Now;

             while (alive)
             {
                 DateTime current = DateTime.Now;
                 TimeSpan span = current - last;
                 last = current;

                 Console.WriteLine("{0}ms", span.Milliseconds);
                 Thread.Sleep(1000 / 60);
             }
         }
     }
 }

最佳答案

只是一个帖子来确认马修的正确答案。 Thread.Sleep() 的准确性受 Windows 时钟中断率的影响。默认情况下,它每秒滴答 64 次,每 15.625 毫秒一次。 Sleep() 只有在发生此类中断时才能完成。这里的心理形象是由“ sleep ”一词引起的,处理器实际上处于 sleep 状态并且不执行代码。只有那个时钟中断会再次唤醒它以恢复执行您的代码。

您选择的 1000/60 是一个非常不愉快的选择,它要求 16 毫秒。略高于 15.625,因此您总是会在至少 2 个滴答后醒来:2 x 15.625 = 31 毫秒。您测量的内容。

但是中断率不是固定的,它可以通过程序改变。它通过调用 CreateTimerQueueTimer() 或遗留的 timeBeginPeriod() 来实现。浏览器通常需要这样做。像动画 GIF 这样简单的事情需要更好的计时器,因为 GIF 帧时间以 10 毫秒为单位指定。或者一般来说,任何与多媒体相关的操作都需要它。

执行此操作的程序的一个非常丑陋的副作用是,这种增加的时钟中断率会产生系统范围的影响。就像它在你的程序中所做的那样。你的计时器突然变得准确了,你实际上得到了你要求的 sleep 时间,16 毫秒。因此 Chrome 正在将速率更改为每秒 1000 次滴答。最大支持。和 good for business当您有竞争操作系统时。

您可以通过选择与默认中断率更接近的 sleep 持续时间来避免此问题。如果您要求 15,那么您将得到 15.625,而 Chrome 无法对此产生影响。 31 是下一个甜蜜点。等等,15.625的整数倍并向下舍入。

更新:请注意此行为已更改 just recently .从 Win10 2004 版本开始,效果不再是全局的,因此 Chrome 无法再影响你的程序。 从 Win11 开始,具有非事件窗口的应用以默认中断率运行。

关于c# - 为什么 Thread.Sleep 在其他应用程序运行时等待的时间比请求的时间长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19415153/

相关文章:

.net - 自定义 CLR 主机 - "Pause"/"Resume"应用程序

c# - 在单个二进制文件中定位多个 .NET 框架?

c# - Xamarin keystore 丢失

c# - 当文件不存在时,File.Delete 不会抛出错误

c# - JavaScript 中的字符串.Format ("{0:n0}")

java - 多线程中内存一致性错误的真实示例?

Android平滑计数器递增

c# - "Member access ' DataType MemberName ' of ' Namespace.ClassName ' not legal on type ' System.Collections.Generic.IEnumerable `1[Namespace.ClassName]."

c# - .NET 3.5 异步 System.Net.Sockets.Socket 停止数据流的原因是什么?

JavaFX:线程异常未记录到系统输出