為了方便測試非同步,先加個計時 計時相關(可以直接跳過該部分) //開始計時 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // 停止計時 stopwatch.Stop(); //輸出計時毫秒數 stopwatch.ElapsedM ...
為了方便測試非同步,先加個計時
計時相關(可以直接跳過該部分)
//開始計時
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 停止計時
stopwatch.Stop();
//輸出計時毫秒數
stopwatch.ElapsedMilliseconds
阻塞延遲,下麵兩個分別表示阻塞三秒鐘
同步阻塞:Thread.Sleep(TimeSpan.FromSeconds(3))
非同步阻塞:Task.Delay(3000)
Thread.Sleep(TimeSpan.FromSeconds(3)):
所屬命名空間:System.Threading.Thread
使用線程阻塞:調用該方法會導致當前線程被阻塞,即掛起當前線程的執行。
同步操作:Thread.Sleep
是同步的,意味著它會阻塞當前線程並占用系統資源。
精度較低:具體的暫停時間不一定非常準確,可能會稍微長一些。
Task.Delay(3000):
所屬命名空間:System.Threading.Tasks.Task
使用任務非同步操作:通過非同步編程模型進行操作,非同步等待指定的時間。
非阻塞操作:Task.Delay
是非同步的,不會阻塞當前線程,而是讓線程可以執行其他任務。
高精度定時器:提供更高的精度,具有更準確的延遲時間。
可以與 async/await 一起使用:await Task.Delay
可以與其他非同步操作一起使用,提供更靈活和響應式的編程體驗。
優缺點比較:
Thread.Sleep
的優點是簡單直接,適用於簡單的線程阻塞場景。然而,它會阻塞當前線程,並且在等待的過程中,當前線程將無法執行其他任務。
Task.Delay
的優點是允許非同步等待一段時間,不會阻塞當前線程,可以與其他非同步操作一起使用,提供更高的性能和響應能力。
此外,它還提供了更準確的定時精度。但是,如果不需要進行非同步編程,或者代碼基於舊版本.NET Framework,可能不適合使用。
介紹非同步幾個關鍵字
Task(任務):Task 是.NET Framework 和 .NET Core 中的一個類型,表示一個非同步操作的單元。它可以被執行、等待和取消,並且可以返回結果。可以通過 Task.Run
方法創建一個 Task。
async/await 關鍵字:async/await 是 C# 5.0 引入的語言特性,用於簡化非同步編程。在方法定義前加上 async
關鍵字來表示這是一個非同步方法,然後可以在方法體內使用 await
關鍵字來暫停方法的執行,等待一個非同步操作完成,然後繼續執行後續的代碼。被 await
修飾的表達式必須是一個返回 Task 或 Task<T> 的非同步方法調用。
await 關鍵字:await
關鍵字用於非同步方法內部,表示等待一個非同步操作完成。當遇到 await
關鍵字時,方法會立即返回給調用者,同時非同步操作開始執行。等待的過程中,線程可以自由地執行其他任務。當非同步操作完成後,該方法會恢復執行,並返回非同步操作的結果。
Task.WhenAll 方法:Task.WhenAll
方法用於等待多個非同步任務完成。它接受一個 Task 數組或可迭代對象作為參數,並返回一個新的 Task,該 Task 在所有傳遞的任務都完成後變為完成狀態。你可以使用 await Task.WhenAll
來等待多個任務同時完成。
常見的屬性
Task.Status 屬性:表示任務的狀態,有以下幾種可能的值:
- Created:任務已創建但未開始執行。
- WaitingForActivation:任務在等待激活,即還未被調度器執行。
- WaitingToRun:任務已被調度器接受,並等待在可用線程上運行。
- Running:任務正在執行。
- WaitingForChildrenToComplete:父任務正在等待其所有子任務完成。
- RanToCompletion:任務成功完成。
- Faulted:任務發生了異常。
- Canceled:任務被取消。
Task.Result 屬性:獲取非同步操作的返回結果。該屬性只能在非同步操作完成後使用,並且會阻塞當前線程直到非同步操作完成。
下麵上代碼示例
async Task Main() { //計時 Stopwatch stopwatch = new Stopwatch(); // 開始計時 stopwatch.Start(); //執行順序和添加順序有關 await Task.WhenAll(A());//先執行A await Task.WhenAll(B());//等待A執行完再執行B List<Task> tasks = new List<Task>() { C(),D() };//等待B執行完後CD一起執行 //也可以逐個添加 //tasks.Add(A()); //tasks.Add(B()); //tasks.Add(C()); //tasks.Add(D()); // 等待CD方法全部完成 await Task.WhenAll(tasks); // 停止計時 stopwatch.Stop(); Console.WriteLine($"計時結束!總共用時:{stopwatch.ElapsedMilliseconds} 毫秒"); } async Task A() { Console.WriteLine("阻塞3秒"); await Task.Delay(3000); Console.WriteLine("3秒結束"); } async Task B() { Console.WriteLine("阻塞2秒"); await Task.Delay(2000); Console.WriteLine("2秒結束"); } async Task C() { Console.WriteLine("阻塞5秒"); await Task.Delay(5000); Console.WriteLine("5秒結束"); } async Task D() { Console.WriteLine("阻塞10秒"); await Task.Delay(10000); Console.WriteLine("10秒結束"); }