There are some methods to release current thread excution right in .NET/C#. They are
Task.Yeild(). The function of these methods is to tell the program to give up current thread and then run another thread. But there are some differences among these methods.
This article is about their differences and theories.
The original link is C#/.NET 中 Thread.Sleep(0), Task.Delay(0), Thread.Yield(), Task.Yield() 不同的执行效果和用法建议. But this blog was written in Chinese, so I translate its content to English. Waterlv is an MVP(Microsoft Most Valuable Professional), and he is good at .NET Core\WPF\.NET. Here is his Blog.
Firstly,I will post the source code of
** 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.
private static extern void SleepInternal(int millisecondsTimeout);
public static void Sleep(int millisecondsTimeout)
// Ensure we don't return to app code when the pause is underway
It is easy to find that in the
Sleep method it calls another method which’s name is
SleepInternal is implemented in CLR, and its function is suspending the current thread for the value of
If we set the value of
milliseconsTimeout to 0 as
Thread.Sleep(0).It will force the current thread to give up the rest of the CPU time slice. Then other threads which have higher priority will run. But if there are not any available threads have higher priority than current thread, this thread will keep running.
If your method will not be affected by other threads, there are not any differences among the methods above. But when your method is affected by multiple threads, other threads may run into this method when you call
Thread.Sleep(0).But it is good news that the CPU time slice for a thread is nanosecond level, so this situation is almost impossible to happen.
Here is the code of
private static extern bool YieldInternal();
public static bool Yield()
And we can notice that
Yield() method calls
YieldInternal() method. And
YieldInternal is implemented in CLR too.
The function of
Thread.Yield() is to force the current thread to give up the rest of CPU time slice, the same as
It is just a little differance between
Thread.Sleep(0), but their function are different.
The current thread will be suspended for timeout milliseconds(here is 1ms). Therefore, during timeout milliseconds current thread will stay at the un-schedulable state. So, other threads will be run even their priority is lower than the current thread.
Here is the result of these three method’s execution time.
Nothing means there are not any codes. And we used
Stopwatch to get the result. For more detail about
Stopwatch visit .NET/C# 在代码中测量代码执行耗时的建议（比较系统性能计数器和系统时间）. This blog was written in Chinese, I will translate it later.
Here is a part of the codes.
var stopwatch = Stopwatch.StartNew();
Task.Delay is a method of TAP. For more informations about TAP,visit Task-based Asynchronous Pattern (TAP) Microsoft Docs.
TAP is a threading model which bases on an async state machine, and this is the biggest difference from the
Here is the source code of
This method will return
Task.CompleteTask as a result when the value of the parameter is
0. That means the code you write after
Task.Delay(0) will be executed immediately. (If the rest of CPU time slice is enough).
The result of
Task.Yield() is a
YeildAwaitable instance and the
YieldAwaitable.GetAwaiter method returns an instance of
YieldAwaiter. So, the result of
Task.Yield method is fully depending on
YieldAwaiter. For more details about
Awaiter visit 如何实现一个可以用 await 异步等待的 Awaiter.
YieldAwaiter relies on
QueueContinuation to determine when to execute subsequent codes. Part of the source codes is listed below.
// Get the current SynchronizationContext, and if there is one,
There are two branches in these codes.
One is setting
DispatcherSynchronizationContextas the value of
SynchronizationContext, then it will call
SynchronizationContextto execute next asynchronous task. The ‘continuation’ means executes the next asynchronous task.
The value of
SynchronizationContextis set as
DispatcherSynchronizationContextfor WPF UI thread, and its
Postmethod is designed to implement the message loop. If other threads have no special setting, the value of
null. For more information,see 出让执行权：Task.Yield, Dispatcher.Yield.
If the value of
SynchronizationContexttype, the codes above will run
elselogic. And its logic is depending on the value of
TaskScheduler.Current, it will find next thread in thread pool or start a
Task.Delay(1) is almost the same as
Task.Delay(0), but the function of these two codes is different.
Task.Delay(1) starts a
System.Threading.Timer instance, and it will describe a callback method which is executed when time is up.
Here is the exact API order to excute the callback
The codes after
await will be encapsulated by the asynchronous state machine and passed to the callback above.
Here is the code of
static extern bool ChangeAppDomainTimer(AppDomainTimerSafeHandle handle, uint dueTime);
And when we call the methods in
Thread, they just affect the scheduling status of the current thread. But when we call the methods in
Task, they will affect the scheduling of the thread pool, then they will call
System.Threading.Timer to count time, the time they consume is more uncontrollable.
Here is the result of the time they consumed.
Nothing means there are not any codes.
The function of
Thread.Yield() is the same in thread scheduling. And
Thread.Sleep(int) will wait for time out and it bases on
Thread.Yield() can be called for giving up current thread’s rest time slice, and give chance to run other threads. If you want to make your thread wait, you can call
If you have to use
async/await , you should use
Task.Yield(). If you use
Task.Delay instead of
Thread.Sleep, it can save resources for one thread.
- Thread.Sleep(0) vs Sleep(1) vs Yeild - stg609 - 博客园
- c# - Task.Delay().Wait(); sometimes causing a 15ms delay in messaging system - Stack Overflow
- c# - When to use Task.Delay, when to use Thread.Sleep? - Stack Overflow
- c# - Should I always use Task.Delay instead of Thread.Sleep? - Stack Overflow
- What’s the difference between Thread.Sleep(0) and Thread,Yield()?