Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么其他应用程序运行时,线程睡眠等待的时间比请求的时间长?_C#_.net_Multithreading_Behavior - Fatal编程技术网

C# 为什么其他应用程序运行时,线程睡眠等待的时间比请求的时间长?

C# 为什么其他应用程序运行时,线程睡眠等待的时间比请求的时间长?,c#,.net,multithreading,behavior,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.Threadi

关于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);
             }
         }
     }
 }

您正在使用
DateTime
解决问题。对于这种精度,您应该使用秒表。该
DateTime
仅精确到30毫秒左右,因此在本例中,您的读数不会告诉您任何信息


测量是你问题的一半。循环的实际时间变化是由于
睡眠
分辨率(如其他答案所述)。

首先,1000/60=16毫秒

PC时钟的分辨率约为18-20ms,
Sleep()
DateTime的结果。现在
将四舍五入到该值的倍数

因此,
Thread.Sleep(5)
Thread.Sleep(15)
将延迟相同的时间。这可能是20、40甚至60毫秒。你没有得到多少保证,
Sleep()
的参数只是最小值

另一个占用CPU的进程(Chrome)(即使是一点点)也会以这种方式影响程序的行为。编辑:这与你所看到的相反,所以这里发生了一些其他的事情。不过,这是关于舍入到时间片的问题

基本上

Thread.Sleep(1000/60)
(其计算结果为
Thread.Sleep(16)
),要求线程进入睡眠状态,并在16毫秒后返回。但是,该线程可能无法再次执行,直到经过更长的时间;比如说,32毫秒


至于为什么Chrome会产生影响,我不知道,但由于Chrome会为每个选项卡生成一个新线程,这将对系统的线程行为产生影响。

这可能是因为Chrome(或Chrome的某些组件)调用的值会提高Windows API函数
Sleep()的分辨率,它是从
Thread.Sleep()
调用的

有关更多信息,请参阅此线程:

几年前,我在Windows Media Player中注意到了这种行为:我们的一个应用程序的行为会根据Windows Media Player是否正在运行而发生变化。事实证明,WMP正在调用
timeBeginPeriod()


然而,一般来说,
Thread.Sleep()
(并且扩展到Windows API
Sleep()
)是非常不准确的。

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

您选择的
1000/60
非常不愉快,需要16毫秒。只比
15.625多一点
,所以你总是会在至少2个节拍后醒来:
2 x 15.625=31毫秒
。你量的

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

程序这样做的一个非常丑陋的副作用是,增加的时钟中断率会对整个系统产生影响。就像在你的节目里一样。你的计时器突然变得准确,你实际上得到了你要求的睡眠时间,16毫秒。所以Chrome正在改变速率,大概是每秒1000个滴答声。支持的最大值。当你有一个竞争对手的操作系统时


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

不要使用
DateTime
进行诊断测试。改用秒表。@Adam Plocher Chrome运行时线程速度是Chrome的两倍,当我关闭它时,它会立即变慢。这里没有问题要解决。睡眠意味着“至少睡这么长时间”,这就是它的作用。当你让一根线睡觉时,它可能再也不会醒来;就肉眼所见,可能有更高优先级的线程。当你说睡眠时,线程调度程序有很大的自由度去做它喜欢做的任何事情,显然当Chrome运行时,它喜欢做一些不同的事情。为什么?谁能说呢?调度程序的行为与文档中描述的一样—它至少休眠了16毫秒—所以不要担心。如果您想知道实际发生了什么,而不是我的随机推测,那么我建议您从阅读Windows内部80页的线程调度算法描述开始如果你对这个主题感兴趣,那么第六版。更一般地说,用零以外的任何参数调用Sleep可能是一个bug。为什么你要花钱创建一个完整的线程,只是为了让它进入睡眠状态?你不会雇佣一个工人然后付钱让他们睡觉。线是昂贵的;如果你不打算使用一个,把它放回池中。我试过秒表,它给我的输出与DateTime相同。DateTime和线程计时器的分辨率基本相同——这并不奇怪——所以使用一个来计时另一个是一个非常糟糕的主意。是的