Thread.Sleep(1)在C#中的影响是什么?
在Windows窗体应用程序中调用Thread.Sleep(1)
的影响是什么,如下面的代码所示:
public Constructor() { Thread thread = new Thread(Task); thread.IsBackground = true; thread.Start(); } private void Task() { while (true) { // do something Thread.Sleep(1); } }
这个线程会占用所有可用的CPU吗?
我可以使用哪些分析技术来衡量此线程的CPU使用率(除了任务pipe理器)?
如上所述,你的循环不会占用CPU。
但要小心 :Windows 不是一个实时的操作系统,所以你不会从Thread.Sleep(1)中获得每秒1000次唤醒。 如果你没有使用timeBeginPeriod来设置你的最小分辨率,你将会每隔15 ms唤醒一次。 即使将最小分辨率设置为1 ms,您仍然每3-4毫秒才会唤醒。
为了获得毫秒级定时器粒度,你必须使用Win32多媒体定时器( C#包装器 )。
不,它不会占用CPU,它会暂停你的线程至less这么长时间。 当线程暂停时,操作系统可以调度另一个不相关的线程来使用处理器。
Thread.Sleep(1)如上所述不会占用CPU。
以下是当一个线程睡眠(或多或less)时发生的情况:
- Thread.Sleep被转换成一个系统调用,然后触发一个陷阱(一个允许操作系统控制的中断)
- 操作系统检测到睡眠呼叫并将您的线程标记为已阻止。
- 操作系统内部保存了需要唤醒的线程列表,以及何时发生。
- 由于线程不再使用CPU的操作系统…
- 如果父进程没有用完所有的时间片,操作系统将调度该进程的另一个线程执行。
- 否则,另一个进程(或空闲进程)将开始执行。
- 当时间到了,你的线程将被再次安排执行,这并不意味着它会自动开始执行。
最后一点,我不完全知道你在做什么,但是你似乎想要扮演调度器的angular色,就是睡觉,为CPU提供时间做其他事情…
在less数情况下(确实很less)可能是好的,但大多数情况下,您应该让调度人员完成工作,这可能比您知道得多 ,而且可以使工作比您做得更好 。
Bob Nadler提到Thread.Sleep(1)
不保证1ms的睡眠时间。
以下是使用Win32多媒体计时器强制进入1ms睡眠的示例。
[DllImport("winmm.dll")] internal static extern uint timeBeginPeriod(uint period); [DllImport("winmm.dll")] internal static extern uint timeEndPeriod(uint period); timeBeginPeriod(1); while(true) { Thread.Sleep(1); // will sleep 1ms every time } timeEndPeriod(1);
在C#GUI应用程序中进行testing,发现应用程序使用了大约50%的CPU。
有关此主题的更多讨论,请参阅以下论坛主题:
应该避免小的睡眠时间,因为放弃其时间片的线程在被重新发送时优先提升,并且这可能导致高的上下文切换。 在multithreading/服务器应用程序中,线程正在为CPU时间而战,这可能会导致抖动效应。 相反,依靠asynchronous函数和同步对象,如临界区或互斥/信号量。
这是一个古老的线索,出现在我的很多search,但Win7有一个新的调度程序,似乎行为不同于上述。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { DateTime dtEnd = DateTime.Now.AddSeconds(1.0); int i = 0; while (DateTime.Now < dtEnd) { i++; Thread.Sleep(1); } Console.WriteLine(i.ToString()); i = 0; long lStart = DateTime.Now.Ticks; while (i++ < 1000) Thread.Sleep(1); long lTmp = (DateTime.Now.Ticks - lStart) / 10000; Console.WriteLine(lTmp.ToString()); Console.Read(); } } }
用上面的代码,我的第一个结果给了946.所以在1秒的时间里,使用1ms的睡眠,我得到了946唤醒。 这非常接近1ms。
第二部分询问需要多长时间以每个1ms进行1000次睡眠事件。 我得到了1034ms。 再次,近1ms。
这是使用.Net 4.0在1.8GHz的core2duo + Win7上
编辑:记住,睡眠(x)这个时候并不意味着醒来,这意味着不要早于这个时间唤醒我。 这是不能保证的。 虽然,可以增加线程的优先级,Windows应该在低优先级的线程之前安排线程。
不,它不会占用所有可用的CPU,因为当另一个线程有工作时,睡眠线程将被OS调度程序切换出来。
不,不会的 你几乎看不到它。 某个地方每秒钟less于1000次的时间,这个线程会在醒来之前再次进入hibernate状态。
编辑:
我必须检查。 在Java 1.5上运行,这个testing
@Test public void testSpeed() throws InterruptedException { long currentTime = System.currentTimeMillis(); int i = 0; while (i < 1000) { Thread.sleep(1); i++; } System.out.println("Executed in " + (System.currentTimeMillis() - currentTime)); }
在我的3ghz机器上每秒钟大约有500次睡眠。 我想C#应该是相当相同的。 我猜想有人会用这个非常重要的现实世界基准testing报告C#编号。 顺便说一下,没有可观察的CPU使用率。
一个线程一次最多可以支持一个(逻辑)CPU。 1ms的睡眠不会被占用。 不要stream汗
也看看这个: msdn论坛
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; namespace Test { public static class Program { public static void Main(string[] args) { Stopwatch sw = new Stopwatch(); for (int i = 0; i < 10; ++i) { sw.Reset(); sw.Start(); Thread.Sleep(50); sw.Stop(); Console.WriteLine("(default) Slept for " + sw.ElapsedMilliseconds); TimeBeginPeriod(1); sw.Reset(); sw.Start(); Thread.Sleep(50); sw.Stop(); TimeEndPeriod(1); Console.WriteLine("(highres) Slept for " + sw.ElapsedMilliseconds + "\n"); } } [DllImport("winmm.dll", EntryPoint="timeBeginPeriod", SetLastError=true)] private static extern uint TimeBeginPeriod(uint uMilliseconds); [DllImport("winmm.dll", EntryPoint="timeEndPeriod", SetLastError=true)] private static extern uint TimeEndPeriod(uint uMilliseconds); } }