結論
同步還是異步,區別如下:
- 同步:你使用 await 修飾符去調用一個異步(async)方法(是異步方法,不過是阻塞式的,可簡單理解爲同步);
- 異步:你獲取異步方法返回的 Task,就是異步(後文有代碼示例);
- 可以實現多任務執行順序執行且不阻塞。
概述
async(C# 參考)
async 是“異步”的簡寫,使用 async 修飾符可將方法、lambda 表達式或匿名方法指定爲異步。
如果對方法或表達式使用此修飾符,則其稱爲異步方法 。
如下示例定義了一個名爲 ExampleMethodAsync
的異步方法:
public async Task<int> ExampleMethodAsync() { //... }
await(C# 參考)
await 運算符暫停對其所屬的 async 方法的求值,直到其操作數表示的異步操作完成。
異步操作完成後,await 運算符將返回操作的結果(如果有)。
當 await 運算符應用到表示已完成操作的操作數時,它將立即返回操作的結果,而不會暫停其所屬的方法。
await 運算符不會阻止計算異步方法的線程。
當 await 運算符暫停其所屬的異步方法時,控件將返回到方法的調用方。
官網說的話是不是聽不明白?沒關係,你就理解爲添加了await 修飾符後,必須要等調用返回後才能繼續執行下一步。
如下示例:
public async Task<int> ExampleMethodAsync() { //... //這添加了await,執行到這裏需要等待MethodAwiat方法執行完成後纔會往下繼續執行。 int result = await MethodAwiat(); //... } public async Task<int> MethodAwiat() { //... }
作用及基本用法
await和async可以簡化我們異步編程,也可以讓我們以一種類似同步編程的方式來進行異步編程。
另外當我們需要不阻塞主線程異步執行,但又要有順序的執行相關代碼的時候,await/async就可以排上用場。
基本用法如下示例:
/// <summary> /// 可異步可同步 /// </summary> /// <returns></returns> public async Task<string> TestAsync() { Thread.Sleep(3000); Task<string> task = new Task<string>(() => { return "主程序返回後我還在執行數據:我是複雜的異步執行的方法,不阻礙主程序執行。。。。。"; }); task.Start(); return await task; } // await 使得任務同步 public async void T1() { // 使用 await 關鍵字,代表等待執行完成,同步 string time = await TestAsync(); Console.WriteLine(time); Console.WriteLine("執行完畢"); } // 直接獲得返回的 Task,實現異步 public void T2() { // 獲取 Task 任務對象,後面的邏輯過程可以弄成異步 Task<string> task = TestAsync(); // 這裏可以處理其它事情,處理完畢後,再獲取執行結果 Console.WriteLine("執行完畢"); Console.WriteLine(task.Result); }
實現多任務順序執行且不阻塞
以微軟文檔的做早餐的案例加以簡化來講解 【使用Async和Await可以實現多任務順序執行且不阻塞】。
主線任務任務:倒橙汁 -> 烤麪包 -> 煎培根 -> 煎雞蛋 -> 倒咖啡。
1.同步執行
我們任務逐步順序執行如下,耗時:17064毫秒(17.064秒):
using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter; using System; using System.Diagnostics; using System.Threading; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); PourOJ(); PourCoffee(); ToastBread(); FryBacon(); FryEggs(); Console.WriteLine("早餐已經做完!"); stopwatch.Stop(); Console.WriteLine($"做早餐總計耗時:{stopwatch.ElapsedMilliseconds}"); Console.ReadLine(); } //倒橙汁 private static void PourOJ() { Thread.Sleep(1000); Console.WriteLine("倒一杯橙汁"); } //烤麪包 private static void ToastBread() { Console.WriteLine("開始烤麪包"); Thread.Sleep(3000); Console.WriteLine("烤麪包好了"); } //煎培根 private static void FryBacon() { Console.WriteLine("開始煎培根"); Thread.Sleep(6000); Console.WriteLine("培根煎好了"); } //煎雞蛋 private static void FryEggs() { Console.WriteLine("開始煎雞蛋"); Thread.Sleep(6000); Console.WriteLine("雞蛋好了"); } //倒咖啡 private static void PourCoffee() { Thread.Sleep(1000); Console.WriteLine("倒咖啡"); } } }
2.並行執行
如果此時我們每一項任務都有一個單獨的人去完成,將會縮短時間將近3倍(當然不能單純的用時間量化他),
如下,耗時6041毫秒(6.041秒):
using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Test(); Console.ReadLine(); } private static void Test() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); List<Task> tasks = new List<Task>() { PourOJ(), ToastBread(), FryBacon(), FryEggs(), PourCoffee() }; Task.WhenAll(tasks).ContinueWith((t) => { Console.WriteLine("早餐已經做完!"); stopwatch.Stop(); Console.WriteLine($"做早餐總計耗時:{stopwatch.ElapsedMilliseconds}"); }); } //倒橙汁 private static async Task PourOJ() { await Task.Delay(1000); Console.WriteLine("倒一杯橙汁"); } //烤麪包 private static async Task ToastBread() { Console.WriteLine("開始烤麪包"); await Task.Delay(3000); Console.WriteLine("烤麪包好了"); } //煎培根 private static async Task FryBacon() { Console.WriteLine("開始煎培根"); await Task.Delay(6000); Console.WriteLine("培根煎好了"); } //煎雞蛋 private static async Task FryEggs() { Console.WriteLine("開始煎雞蛋"); await Task.Delay(6000); Console.WriteLine("雞蛋好了"); } //倒咖啡 private static async Task PourCoffee() { await Task.Delay(1000); Console.WriteLine("倒咖啡"); } } }
3.並行且可指定順序執行
但是我們不可能每次做早餐都有那麼多人同時做,
需求變更:如果現在要求,先倒橙汁,然後倒咖啡,其餘的操作並行執行,應該如何操作呢?
只需將以上案例的主線程Test 方法修改如下,其他的不變,耗時8073毫秒(8.073秒):
private static async void Test() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); await PourOJ(); //倒橙汁 await PourCoffee(); //然後倒咖啡 List<Task> tasks = new List<Task>() { ToastBread(), FryBacon(), FryEggs() };//子任務List await Task.WhenAll(tasks); //其餘的並行操作 Console.WriteLine("早餐已經做完!"); stopwatch.Stop(); Console.WriteLine($"做早餐總計耗時:{stopwatch.ElapsedMilliseconds}"); }
總結
我們發現,用好了async和await確實很節省時間。
大家可以想想怎麼優雅的在異步裏面開多線程(多主線程多子線程)最節省時間。
參考文獻
喜歡就點贊加關注。
歡迎關注訂閱微信公衆號【熊澤有話說】,更多好玩易學知識等你來取
作者:熊澤-學習中的苦與樂
公衆號:熊澤有話說
QQ羣:711838388
出處:https://www.cnblogs.com/xiongze520/p/16976940.html
您可以隨意轉載、摘錄,但請在文章內註明作者和原文鏈接。