I am trying to write the ultimate "Yield" method to yield the current time slice to other threads. So far I have found that there are several different ways to make the thread yield its allocated time slice. I just want to make sure I am interpreting them correctly since the documentation is not very clear. So, from what I have read on stackoverflow, MSDN and various blog posts, the following options exist that all have different advantages / disadvantages:
SwitchToThread
[win32] / Thread.Yield
[.NET 4 Beta 1]: yields to any thread on same processor
- Advantage: about twice as fast as
Thread.Sleep(0)
- Disadvantage: yields only to threads on same processor
Thread.Sleep(0)
: yields to any thread of same or higher priority on any processor
- Advantage: faster than
Thread.Sleep(1)
- Disadvantage: yields only to threads of same or higher priority
Thread.Sleep(1)
: yields to any thread on any processor
- Advantage: yields to any thread on any processor
- Disadvantage: slowest option
(
Thread.Sleep(1)
will usually suspend the thread by about 15ms iftimeBeginPeriod
/timeEndPeriod
[win32] are not used)
What about Thread.SpinWait
? Can that be used for yielding the time slice of the thread? If not, what is it used for?
I there something else I have missed or incorrectly interpreted. I'd be grateful if you could correct / add to my understanding.
This is how my Yield method looks like so far:
public static class Thread
{
[DllImport("kernel32.dll")]
static extern bool SwitchToThread();
[DllImport("winmm.dll")]
internal static extern uint timeBeginPeriod(uint period);
[DllImport("winmm.dll")]
internal static extern uint timeEndPeriod(uint period);
/// <summary> yields time slice of current thread to specified target threads </summary>
public static void YieldTo(ThreadYieldTarget threadYieldTarget)
{
switch (threadYieldTarget) {
case ThreadYieldTarget.None:
break;
case ThreadYieldTarget.AnyThreadOnAnyProcessor:
timeBeginPeriod(1); //reduce sleep to actually 1ms instead of system time slice with is around 15ms
System.Threading.Thread.Sleep(1);
timeEndPeriod(1); //undo
break;
case ThreadYieldTarget.SameOrHigherPriorityThreadOnAnyProcessor:
System.Threading.Thread.Sleep(0);
break;
case ThreadYieldTarget.AnyThreadOnSameProcessor:
SwitchToThread();
break;
default: throw new ArgumentOutOfRangeException("threadYieldTarget");
}
}
}
public enum ThreadYieldTarget
{
/// <summary> Operation system will decide when to interrupt the thread </summary>
None,
/// <summary> Yield time slice to any other thread on any processor </summary>
AnyThreadOnAnyProcessor,
/// <summary> Yield time slice to other thread of same or higher piority on any processor </summary>
SameOrHigherPriorityThreadOnAnyProcessor,
/// <summary> Yield time slice to any other thread on same processor </summary>
AnyThreadOnSameProcessor
}
See Question&Answers more detail:os