views:

3597

answers:

8

In a windows form application what is the impact of calling Thread.Sleep(1) as illustrated in the following code:

public Constructor()
{
    Thread thread = new Thread(Task);
    thread.IsBackground = true;
    thread.Start();
}

private void Task()
{
    while (true)
    {
        // do something
        Thread.Sleep(1);
    }
}

Will this thread hog all of the available CPU?

What profiling techniques can I use to measure this Thread's CPU usage ( other than task manager )?

+20  A: 

No it won't hog the CPU, it will just pause your thread for at least that long. While your thread is paused, the operating system can schedule another, unrelated thread to make use of the processor.

Frederick
It would hog a LOT of cpu time unnecessarily, though.
Joel Coehoorn
@Joel How/why would it hog more time than a while (true) { i++; }or is it essentially the same in terms of CPU usage?
On a modern CPU a 1ms sleep is an eternity compared to doing i++.
Serguei
+1  A: 

No, it won't hog all available CPU, because a sleeping thread will be switched out by the OS' scheduler when another thread has work to do.

DannySmurf
+1  A: 

No, it will not. You'll barely see it. Somewhere less than 1000 times a second this thread will wake up and do next to nothing before sleeping again.

Edit:

I had to check. Running on Java 1.5 , this test

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

Ran at approximately 500 sleeps per second on my 3ghz machine. I suppose C# should be fairly much the same. I assume someone will report back with C# numbers for this intensely important real-world benchmark. There was no observable CPU usage, by the way.

krosenvold
I doubt it would happen even that often: the argument to sleep is a minimum time, and context switching takes too long to get the many in anyway.
Joel Coehoorn
On modern multicore systems 1ms is a mighty long time. I wonder how this loop would actually run ?
krosenvold
+11  A: 

As stated, your loop will not hog the CPU.

But beware: Windows is not a real-time OS, so you will not get 1000 wakes per second from Thread.Sleep(1). If you haven't used timeBeginPeriod to set your minimum resolution you'll wake about every 15 ms. Even after you've set the minimum resolution to 1 ms, you'll still only wake up every 3-4 ms.

In order to get millisecond level timer granularity you have to use the Win32 multimedia timer (C# wrapper).

Bob Nadler
Could you give an example of setting up timeBeginPeriod in C#?
Justin Tanner
http://www.pinvoke.net/default.aspx/winmm.timeBeginPeriodAccording to the MSDN doc, timeBeginPeriod should be matched with a timeEndPeriod call. Also note that "This function affects a global Windows setting." and can affect system performance.
Bob Nadler
A: 

A thread can at most hog one (logical) CPU at a time. And a 1ms sleep will not be hogging. Don't sweat it.

Andrei Rinea
+8  A: 

Thread.Sleep(1) as stated will not hog the CPU.

Here is what happens when a thread sleeps (more or less):

  • Thread.Sleep is translated into a system call, which in turn triggers a trap (an interruption that allows the operating system to take control)
  • The operating system detects the call to sleep and marks your thread as blocked.
  • Internally the OS keeps a list of threads that need to be waken up and when it should happen.
  • Since the thread is no longer using the CPU the OS...
  • If the parent process has not used up all of its time slice the OS will schedule another thread of the process for execution.
  • Otherwise another process (or the idle process) will start executing.
  • When the time is due, your thread will be scheduled again for execution, that doesn't mean it will start executing automatically.

On a final note, I don't exactly know what you are doing but it would seem you're trying to take the role of the scheduler, that is, sleeping to provide the CPU with time to do other things...

In a few cases (very few indeed) it might be all right, but mostly you should let the scheduler do its work, it probably knows more than you do, and can make the work better than you can do it.

Jorge Córdoba
+1  A: 

As Bob Nadler mentioned Thread.Sleep(1) does not guarantee a sleep time of 1ms.

Here is an example using the Win32 multimedia timer to force a sleep of 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);

Testing this in a C# GUI application, I found that the application used about 50% of my CPU.

For more discussion on this topic see the following forum thread:

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

Justin Tanner