Я пытаюсь написать окончательный метод "Yield" для выдачи текущего отрезка времени другим потокам. До сих пор я обнаружил, что есть несколько различных способов заставить поток выдавать выделенный ему временной интервал. Я просто хочу убедиться, что я правильно их интерпретирую, поскольку документация не очень понятна. Итак, из того, что я прочитал о stackoverflow, MSDN и различных постах в блоге, существуют следующие варианты, которые имеют разные преимущества / недостатки:
SwitchToThread
[win32] / Thread.Yield
[.NET 4 Beta 1]: уступает любому потоку на одном процессоре
- Преимущество: примерно в два раза быстрее, чем
Thread.Sleep(0)
- Недостаток: уступает только темам
на том же процессоре
Thread.Sleep(0)
: уступает любому потоку с таким же или более высоким приоритетом на любом процессоре
- Преимущество: быстрее, чем
Thread.Sleep(1)
- Недостаток: уступает только темам
с таким же или более высоким приоритетом
Thread.Sleep(1)
: уступает любому потоку на любом процессоре
- Преимущество: уступает любому потоку на
любой процессор
- Недостаток: самый медленный вариант
(
Thread.Sleep(1)
будет обычно
приостановить поток примерно на 15 мс, если
timeBeginPeriod
/ timeEndPeriod
[win32] не используются)
А как насчет Thread.SpinWait
? Можно ли это использовать для получения отрезка времени потока? Если нет, то для чего он используется?
Я что-то еще пропустил или неправильно истолковал. Я был бы признателен, если бы вы могли исправить / дополнить мое понимание.
Вот так выглядит мой метод Yield:
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
}