SYSK 152: Comparison of DoEvents, Sleep and SpinWait

There are several ways to yield processing time.  One common method used is to call Application.DoEvents();  This method processes all Windows messages currently in the message queue. 

 

Another frequently used method is to invoke Thread.Sleep(milliseconds) , or a less known Thread.SpinWait(numberOfIterations)

 

It’s important to note that SpinWait keeps the calling thread active on the processor, and, as such, avoid excessive context switching, while Sleep results in the calling thread being preempted off the processor.

 

Calling SpinWait or Sleep methods is preferable to coding an explicit busy loop because the hardware can be informed that it is busy waiting.

 

The commonly asked follow-up question is “what is an iteration”?  From what I was able to dig out, an iteration is measured in processor clock cycles (read:  on different processors an iteration will take different amount of time).  1 iteration » 2 clock cycles »100,000 instructions (your instructions “mileage” may vary).

 

With today’s hardware, 1 iteration < 1 millisecond, so, normally, you’d call SpinWait instead of Sleep if 1 millisecond is too long to wait…  Granted, you could call Sleep(0) to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run.  However, using Sleep(0) can lead to priority inversion (if need a refresher on this, check out a good description of priority inversion at http://en.wikipedia.org/wiki/Priority_inversion).  As previously stated, Sleep(0) only yields the processor if there's another thread of the same priority that's ready to run.  If a high-priority thread is trying to acquire the lock, which is held by a low-priority thread, then the low-priority thread may never get scheduled and hence never free the lock.  The operating system kernel attempts to avoid priority inversions by temporarily boosting the priority of low-priority threads in ‘ready-to-run’ state, but the problem can still occur if there's a medium-priority thread that's always in the ‘ready-to-run’ state.  If Sleep(1) is used, then the thread unconditionally yields the CPU.