C#中的Task.Delay()和Thread.Sleep()差別
一、簡介
1.Thread.Sleep()是同步延遲,Task.Delay()是異步延遲。
2.Thread.Sleep()會阻塞線程,Task.Delay()不會。
3.Thread.Sleep()不能取消,Task.Delay()可以。
4.Task.Delay()實質建立一個運作給定時間的任務,Thread.Sleep()使目前線程休眠給定時間。
5.反編譯Task.Delay(),基本上講它就是個包裹在任務中的定時器。
6.Task.Delay()和Thread.Sleep()最大的差別是Task.Delay()旨在異步運作,在同步代碼中使用Task.Delay()是沒有意義的;在異步代碼中使用Thread.Sleep()是一個非常糟糕的主意。通常使用await關鍵字調用Task.Delay()。
二、代碼案例
案例一:Thread.Sleep()和Task.Delay()比較
代碼:
static void Main(string[] args)
{
//阻塞,出現CPU等待...
Task.Factory.StartNew(delegate
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ****** Start Sleep()******");
for (int i = 1; i <=10; i++)
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "******Sleep******==>" + i);
Thread.Sleep(1000);//同步延遲,阻塞一秒
}
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ******End Sleep()******");
Console.WriteLine();
});
//不阻塞
Task.Factory.StartNew(() =>
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======StartDelay()======");
for (int i =1; i <=10; i++)
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======Delay====== ==>" + i);
Task.Delay(1000);//異步延遲
}
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======End Delay()======");
Console.WriteLine();
});
Console.ReadLine();
Console.ReadKey();
}
結果:
通過運作結果截圖對比看出,Thread.Sleep()是同步延遲,Task.Delay()是異步延遲。

案例二:通過async/await實作Task.Delay()同步
//該段代碼通過async/awatit實作“同步”Delay
static void Main(string[] args)
{
Task.Factory.StartNew(async () =>
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======Start Delay()======");
for (int i = 1; i <=10; i++)
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======Delay======" + i);
await Task.Delay(1000);
}
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======End Delay()======");
});
Console.ReadKey();
}
運作結果可以看出,通過async/await實作了Task.Delay()同步
案例三:Task.Delay()取消
class Program
{
#region
CancellationTokenSource cts = new CancellationTokenSource();
void PutThreadSleep()
{
Thread.Sleep(5000);
}
async Task PutTaskDelay()
{
try
{
await Task.Delay(5000, cts.Token);//需要.net4.5的支援
}
catch (TaskCanceledException ex)
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff ==>") + ex.ToString());
}
}
private void ThreadSleep()
{
PutThreadSleep();
Console.WriteLine("Sleep : I am back");
}
private async void TaskDelay()
{
await PutTaskDelay();
Console.WriteLine("Delay : I am back");
}
private void CancelTaskDelay()
{
cts.Cancel();
}
#endregion
static void Main(string[] args)
{
#region
Program p = new Program();
//不可取消
p.ThreadSleep();
//可取消
p.TaskDelay();
p.CancelTaskDelay();
#endregion
Console.ReadKey();
}
}
Task.Delay()取消,抛出異常資訊。
三、總結
Task.Delay(),async/await和CancellationTokenSource組合起來使用可以實作可控制的異步延遲。
本文來自部落格園,作者:農碼一生,轉載請注明原文連結:https://www.cnblogs.com/wml-it/p/14850246.html
技術的發展日新月異,随着時間推移,無法保證本部落格所有内容的正确性。如有誤導,請大家見諒,歡迎評論區指正! 個人開源代碼連結: GitHub:https://github.com/ITMingliang
Gitee:https://gitee.com/mingliang_it
GitLab:https://gitlab.com/ITMingliang
進開發學習交流群: