在 C#/.NET 中,有 Thread.Sleep(0)
, Task.Delay(0)
, Thread.Yield()
, Task.Yield()
中,有几种不同的让当前线程释放执行权的方法。他们的作用都是放弃当前线程当前的执行权,让其他线程得以调度。但是他们又不太一样。
本文说说他们的原理区别和用法区别。
本文内容
原理区别
Thread.Sleep(0)
Thread.Sleep(int millisecondsTimeout)
的代码贴在下面,其内部实际上是在调用 SleepInternal
,而 SleepInternal
由 CLR 内部实现。其目的是将当前线程挂起一个指定的时间间隔。
如果将超时时间设置为 0,即 Thread.Sleep(0)
,那么这将强制当前线程放弃剩余的 CPU 时间片。
放弃当前线程剩余的 CPU 时间片就意味着其他比此线程优先级高且可以被调度的线程将会在此时被调度。然而此方法只是放弃当前 CPU 执行的时间片,如果当前系统环境下其他可以被调度的其他线程的优先级都比这个线程的优先级低,实际上此线程依然还是会优先执行。
如果你的方法不会被其他线程影响,那么不会有执行上的区别,但如果你的方法涉及到多个线程的调用,那么 Thread.Sleep(0)
的调用可能导致其他线程也进入此方法(而不是等此线程的当前时间片执行完后再进入)。当然,CPU 对单个线程的执行时间片是纳秒级别的,所以实际上你因为此方法调用获得的多线程重入效果是“纯属巧合”的。
/*=========================================================================
** Suspends the current thread for timeout milliseconds. If timeout == 0,
** forces the thread to give up the remainer of its timeslice. If timeout
** == Timeout.Infinite, no timeout will occur.
**
** Exceptions: ArgumentException if timeout < 0.
** ThreadInterruptedException if the thread is interrupted while sleeping.
=========================================================================*/
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void SleepInternal(int millisecondsTimeout);
[System.Security.SecuritySafeCritical] // auto-generated
public static void Sleep(int millisecondsTimeout)
{
SleepInternal(millisecondsTimeout);
// Ensure we don't return to app code when the pause is underway
if(AppDomainPauseManager.IsPaused)
AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
}
Thread.Yield()
Thread.Yield()
的代码贴在下面,其内部调用 YieldInternal
,实际上也是由 CLR 内部实现。
此方法也是放弃当前线程的剩余时间片,所以其效果与 Thread.Sleep(0)
是相同的。
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
[HostProtection(Synchronization = true, ExternalThreading = true),
ReliabilityContract(Consistency.WillNotCorruptState,