Thread.Sleep is a sign of a poorly-designed program, redux

My post on Thread.Sleep was a slight generalization.  I say that Thread.Sleep is a sign of a poorly design program because *usually* when Thread.Sleep is used it used for timing and not used for what it’s can safely be used for.

Using Thread.Sleep with a timeout other than 1 usually means the developer doesn’t understand what Thread.Sleep does.  A value other than one means the system might pause the thread for that number of milliseconds.  In reality it might be less than the requested milliseconds and in all likelihood it will be more–potentially much more.

I won’t get back into the consequences of using Thread.Sleep.  I’ll just touch on one way (which I think is the only way) to use Thread.Sleep correctly.

Thread.Sleep accepts one parameter, the recommended minimum milliseconds to relinquish control of the CPU.  That value has three special values: 0, 1, -1.  -1 (or Timeout.Infinite). in typical Windows form, means infinite and can only be awoken by aborting the thread.  0 means relinquish control of the rest of the time slice to another waiting thread of equal priority and go into a ready state–potentially returning immediately if no other threads are waiting.  A value between 0 and infinite means relinquish control of the CPU for a recommended minimum milliseconds and return the thread to a ready state after that amount of time.

Since the value given to Thread.Sleep is a recommendation and that the actual period depends on the CPU’s clock resolution and the granularity of the Windows scheduler, Thread.Sleep can’t be used for reliable timing.

One useful thing you can get out of Thread.Sleep is to pass it a value of 1.  This has the same effect of Thread.Sleep(0) but allows *any* waiting thread to get CPU time.  This is a nice way for an application to “play nice” with the rest of the system, essentially saying “if anyone needs the CPU, I don’t need it right now; help yourself”.  In applications that need to loop-test for things, this is a good way to avoid having them consume 100% of the CPU.  But, there’s often a better design to loop-testing.

1 really means the rest of the time slice because of the granularity of the scheduler; but I like the convention of “1” to make it distinct.

A recap of the advice I’ve given since “Thread.Sleep is a sign of a poorly designed program”:

  • For scheduled logic, use a timer–don’t use Thread.Sleep()
  • For accurate delays, schedule them; don’t use Thread.Sleep()
  • For the most accurate timing, use the native multimedia timers; don’t use Thread.Sleep()
  • And to clarify: Thread.Sleep(x) is a sign of a poorly designed program where x != 1.

Leave a Reply

Your email address will not be published. Required fields are marked *