代码之家  ›  专栏  ›  技术社区  ›  Justin Tanner

C#中的线程睡眠(1)有什么影响?

  •  29
  • Justin Tanner  · 技术社区  · 16 年前

    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使用率(任务管理器除外)?

    10 回复  |  直到 16 年前
        1
  •  45
  •   Bob Nadler    16 年前

    如上所述,您的循环不会占用CPU。

    但是要小心 :Windows是 一个实时操作系统,所以你会 timeBeginPeriod 要设置最低分辨率,您将大约每15毫秒醒来一次。即使将最低分辨率设置为1毫秒,您仍然只会每3-4毫秒醒来一次。

    C# wrapper ).

        2
  •  28
  •   G S    14 年前

    不,它不会占用CPU,它只会暂停线程一段时间 至少

        3
  •  20
  •   Jorge Córdoba    16 年前

    如上所述的休眠(1)不会占用CPU。

    • Sleep被转换成一个系统调用,这反过来会触发一个陷阱(一种允许操作系统控制的中断)
    • 操作系统检测到对睡眠的调用,并将线程标记为阻塞。
    • 操作系统内部保存了一个需要唤醒的线程列表,以及何时唤醒。
    • 如果父进程没有用完所有的时间片,操作系统将安排进程的另一个线程执行。
    • 否则,另一个进程(或空闲进程)将开始执行。
    • 当时间到期时,您的线程将再次被安排执行,这并不意味着它将自动开始执行。

    最后一点,我不知道你到底在做什么,但你似乎在尝试扮演调度程序的角色,也就是说,睡眠为CPU提供了做其他事情的时间。。。

    你能把工作做得比你更好 .

        4
  •  5
  •   Tim Lehner    12 年前

        5
  •  4
  •   Justin Tanner    16 年前

    正如Bob Nadler提到的 Thread.Sleep(1) 不能保证1毫秒的睡眠时间。

    下面是一个使用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应用程序中测试这一点,我发现该应用程序占用了我大约50%的CPU。

    http://www.dotnet247.com/247reference/msgs/57/289291.aspx

        6
  •  4
  •   Bengie    14 年前

    这是一个在我的很多搜索中出现的旧线程,但是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();
            }
        }
    }
    

    第二部分询问以1ms的速度进行1000次睡眠事件需要多长时间。我有1034M。同样,接近1ms。

    这是在使用.NET4.0的1.8ghz core2duo+Win7上实现的

    编辑:记住,睡眠(x)并不意味着在这个时候醒来,它意味着不早于这个时间叫醒我。这不是保证。尽管如此,您可以提高线程的优先级,Windows应该在低优先级线程之前安排线程。

        7
  •  2
  •   TheSmurf    16 年前

        8
  •  2
  •   krosenvold    16 年前

    不,不会的。你几乎看不到。在每秒不到1000次的某个地方,这个线程会在再次睡觉之前醒来,几乎什么都不做。

    我必须检查一下。此测试在Java1.5上运行

    @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#应该大致相同。我想有人会用这个非常重要的现实基准的C#数字来报告。顺便说一下,没有可观察到的CPU使用情况。

        9
  •  0
  •   Andrei Rînea    16 年前

        10
  •  0
  •   FrankyHollywood    13 年前

    也可以看看这个: msdn forum

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