3

I was reading over some threading basics and on the msdn website I found this snippet of code.

    // Put the main thread to sleep for 1 millisecond to
    // allow the worker thread to do some work:
    Thread.Sleep(1);

Here is a link to the the page: http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx.

Why does the main thread have sleep for 1 millisecond? Will the secondary thread not start its tasks if the main thread is continuously running? Or is the example meant for a task that takes 1 millisecond to do? As in if the task generally takes 5 seconds to complete the main thread should sleep for 5000 milliseconds?

If this is solely regarding CPU usage, here is a similar Question about Thread.Sleep.

Any comments would be appreciated.

Thanks.

Community
  • 1
  • 1
YahooMania
  • 115
  • 4
  • 15

5 Answers5

7

The 1 in that code is not terribly special; it will always end up sleeping longer than that, as things aren't so precise, and giving up your time slice does not equal any guarantee from the OS when you will get it back.

The purpose of the time parameter in Thread.Sleep() is that your thread will yield for at least that amount of time, roughly.

So that code is just explicitly giving up its time slot. Generally speaking, such a bit of code should not be needed, as the OS will manage your threads for you, preemptively interrupting them to work on other threads.

This kind of code is often used in "threading examples", where the writer wants to force some artificial occurrence to prove some race condition, or the like (that appears to be the case in your example)


As noted in Jon Hanna's answer to this same question, there is a subtle but important difference between Sleep(0) and Sleep(1) (or any other non-zero number), and as ChrisF alludes to, this can be important in some threading situations.

Both of those involve thread priorities; Threads can be given higher/lower priorities, such that lower priority threads will never execute as long as there are higher priority threads that have any work to do. In such a case, Sleep(1) can be required... However...

Low-priority threads are also subject to what other processes are doing on the same system; so while your process might have no higher-priority threads running, if any others do, yours still won't run.

This isn't usually something you ever need to worry about, though; the default priority is the 'normal' priority, and under most circumstances, you should not change it. Raising or lowering it has numerous implications.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • So that bit of code is actually defeating the purpose of threads? As the purpose is to execute multiple tasks at once without having to wait for each other to finish. It is better practice to not use that? – YahooMania Dec 19 '11 at 23:41
  • @YahooMania No, it's vital to do so in some cases. – Jon Hanna Dec 19 '11 at 23:56
  • @YahooMania But you aren't necessarily all that likely to come across such a situation, outside of threading examples. That bit of code exists to help illustrate a point. – Andrew Barber Dec 20 '11 at 00:01
  • @AndrewBarber outside of threading examples and real-life threading code, which surely is the whole point of reading the treading examples. Sure it's contrived in this case, but not explaining the importance of giving up the slice if you've waited too long for a condition that depends on another thread defeats the purpose of someone trying to learn about threading. – Jon Hanna Dec 20 '11 at 00:07
  • @AndrewBarber See my answer near the bottom. – YahooMania Dec 20 '11 at 23:18
  • @JonHanna See my answer near the bottom. – YahooMania Dec 20 '11 at 23:19
4

Thread.Sleep(0) will give up the rest of a thread's time-slice if a thread of equal priority is ready to schedule.

Thread.Sleep(1) (or any other value, but 1 is the lowest to have this effect) will give up the rest of the thread's time-slice unconditionally. If it wants to make sure that even threads with lower priority have a chance to run (and such a thread could be doing something that is blocking this thread, it has to), then it's the one to go for.

http://www.bluebytesoftware.com/blog/PermaLink,guid,1c013d42-c983-4102-9233-ca54b8f3d1a1.aspx has more on this.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
2

If the main thread doesn't sleep at all then the other threads will not be able to run at all.

Inserting a Sleep of any length allows the other threads some processing time. Using a small value (of 1 millisecond in this case) means that the main thread doesn't appear to lock up. You can use Sleep(0), but as Jon Hanna points out that has a different meaning to Sleep(1) (or indeed any positive value) as it only allows threads of equal priority to run.

If the task takes 5 seconds then the main thread will sleep for a total of 5,000 milliseconds, but spread out over a longer period.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
0

It's only for the sake of the example- they want to make sure that the worker thread has the chance to print "worker thread: working..." at least once before the main thread kills it.

As Andrew implied, this is important in the example especially because if you were running on a single-processor machine, the main thread may not give up the processor, killing the background thread before it has a chance to iterate even once.

Chris Shain
  • 50,833
  • 6
  • 93
  • 125
0

Interesting thing I noticed today. Interrupting a thread throws a ThreadInterruptedException. I was trying to catch the exception but could not for some reason. My coworker recommended that I put Thread.Sleep(1) prior to the catch statement and that allowed me to catch the ThreadInterruptedException.

        // Start the listener
        tcpListener_ = new TcpListener(ipAddress[0], int.Parse(portNumber_));
        tcpListener_.Start();
        try
        {
            // Wait for client connection
            while (true)
            {
                // Wait for the new connection from the client
                if (tcpListener_.Pending())
                {
                    socket_ = tcpListener_.AcceptSocket();
                    changeState(InstrumentState.Connected);

                    readSocket();
                }
                Thread.Sleep(1);
            }
        }

        catch (ThreadInterruptedException) { }

        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Contineo", MessageBoxButtons.OK, MessageBoxIcon.Error);
            Console.WriteLine(ex.StackTrace);
        }

Some other class...

        if (instrumentThread_ != null)
        {
            instrumentThread_.Interrupt();
            instrumentThread_ = null;
        }
YahooMania
  • 115
  • 4
  • 15
  • It could also have been caught if you'd taken out the `Pending()` test and just let `AcceptSocket()` block prior to the `Start`. The reason is an extension of my answer. The thread won't have `ThreadInterruptedException` thrown on it until it blocks or gives up its time-slice (not just come to the end of its quanta and go back to waiting for the next quanta) which `Thread.Sleep(1)` causes, but `Thread.Sleep(0)` doesn't. Entering a monitor or waiting on an event would also have given it a chance to be thrown. – Jon Hanna Dec 20 '11 at 23:30