談談對.NET中async/await的理解
一、什么是同步?什么是異步?
在.net中,async 和 await 是兩個關鍵字,async 關鍵字用于聲明一個方法是異步方法,該方法可以包含一個或多個 await 表達式。await 關鍵字是用于在異步方法中等待一個任務(Task 或 Task<T>對象)的完成。在 async 方法中使用 await表達式時,會暫停當前方法的執(zhí)行,直到等待的任務完成。在這段時間內,主線程可以去執(zhí)行其它操作。
什么是同步:當一個方法被調用時,調用者需要等待該方法執(zhí)行完畢后才會繼續(xù)往下執(zhí)行,我們稱這種方法為同步方法。
什么是異步:當一個方法被調用時立即返回,并獲取一個線程執(zhí)(Task)行該方法內部的業(yè)務邏輯,而調用者不需要等待這個方法執(zhí)行完畢,我們稱這種方法為異步方法。
二、async/await是怎么提高性能的?
異步的好處在于非阻塞(調用線程不會暫停執(zhí)行去等待子線程完成),因此,我們可以把一些不需要立即使用結果、耗時的任務設為異步去執(zhí)行,可以提高程序的執(zhí)行效率。
比如,一個主線程需要執(zhí)行 5 個方法,假設每個方法的分別用時為 0.1s、0.2s、0.3s、0.4s、0.5s,如果在同步編程中,這個主線程的執(zhí)行用時大概為1.5秒。而如果把這5個方法寫成異步的形式,那么這個主線程大概用時為0.5秒。
這是為什么呢?這是因為,在同步方法中,主線程在調用方法時,需要把這個方法執(zhí)行完成之后再繼續(xù)調用后續(xù)的方法,主線程執(zhí)行這5個方法就好比一根線穿5顆珠子一樣,一顆一顆來,所以主線程執(zhí)行所用時間大概為1.5秒。而在異步方法中,主線程在調用異步方法時,主線程不會立即去執(zhí)行異步方法的,而是在遇到異步方法中的 await語句后返回一個任務(Task),然后再繼續(xù)調用后續(xù)的方法,這些任務的執(zhí)行是由 task創(chuàng)建一個子線程去執(zhí)行的,主線程執(zhí)行這5個異步方法就好比5個人拿5根線同時穿5顆珠子,所用時間就是用時最多的那個,所以主線程執(zhí)行時間大概為0.5秒。
問題:怎么解決在調用異步函數(shù)時,主線程繼續(xù)向下執(zhí)行后,主線程是怎么回收或管理這個異步方法的執(zhí)行結果的。
1、await等待執(zhí)行
public class Demo { public async Task DemoAsync() { await Task.Delay(1000); Console.WriteLine("1秒后執(zhí)行"); } } public Class Program { static async Task Main(string[] args) { Demo demo = new Demo(); // 使用 await 等待DemoAsync的執(zhí)行 await demo.DemoAsync(); Console.ReadKey(); } }
2、使用事件
internal class Program { static void Main(string[] args) { Demo demo = new Demo(); demo.OnEvent += (() => { Console.WriteLine("事件訂閱"); }); demo.DemoAsync(); Console.ReadKey(); } } public class Demo { public event Action OnEvent; public async Task DemoAsync() { Console.WriteLine("開始執(zhí)行"); await Task.Delay(1000); Console.WriteLine("1秒后執(zhí)行"); OnEvent?.Invoke(); } }
3、回調函數(shù)
internal class Program { static void Main(string[] args) { Demo demo = new Demo(); demo.DemoAsync(() => { Console.WriteLine("回調函數(shù)"); }); Console.ReadKey(); } } public class Demo { public async Task DemoAsync(Action callback) { Console.WriteLine("開始執(zhí)行"); await Task.Delay(1000); callback?.Invoke(); Console.WriteLine("1秒后執(zhí)行"); } }
4、使用異步方法但不等待結果
這種方法知識啟動了異步操作而不需要結果,可以簡單的調用異步方法而不使用 await。這種方式不會阻塞主線程,也不會處理異步操作的結果。
internal class Program { static void Main(string[] args) { Demo demo = new Demo(); demo.DemoAsync(); Console.ReadKey(); } } public class Demo { public async Task DemoAsync() { Console.WriteLine("開始執(zhí)行"); await Task.Delay(1000); Console.WriteLine("1秒后執(zhí)行"); } }
5、將異步結果存儲在變量中
如果想要在某個時刻獲取到異步操作中的結果,可以將異步操作的結果存儲在變量中,然后再訪問它。
internal class Program { static void Main(string[] args) { Demo demo = new Demo(); var demoResult = demo.DemoAsync(); // 使用 wait等待異步的完成 demoResult.Wait(); if (demoResult.IsCompleted) { Console.WriteLine("str執(zhí)行完成"); Console.WriteLine(demoResult.Result); } Console.ReadKey(); } } public class Demo { public async Task<string> DemoAsync() { Console.WriteLine("開始執(zhí)行"); await Task.Delay(1000); Console.WriteLine("1秒后執(zhí)行"); return "異步返回結果"; } }
三、異步到底解決了什么?到底起到了什么樣的作用?
1、提高響應性:使用 async 和 await 可以避免等待長時間運行的操作(如 IO 操作)阻塞主線程,從而提高應用程序的響應性。
2、簡化異步操作:async 和 await 使得編寫異步代碼更接近同步代碼的寫法,這降低了異步編程的復雜性和出錯的概率。
3、優(yōu)化資源使用:異步操作允許線程在等待任務完成時釋放,這樣可以為其它任務騰出資源,而不是處于空閑等待狀態(tài)。
四、在使用異步時的一些問題的解決
1、異步的傳遞性問題
異步方法的異步效果會在調用鏈上向上傳遞的,導致異步方法的調用鏈上的一些列方法也會被標記為異步。這種情況通常發(fā)生在下面場景中:
調用異步方法:如果一個方法調用了一個異步方法,那么這個方法也需要標記為 async,并使用 await 等待結果。返回類型的變化:異步方法通常以 Task 或 Task<T> 類型返回,這意味著調用這些異步方法的其他方法也需要更新其返回類型以匹配 Task 或 Task<T> 。
異步方法的傳遞性的避免:
1、不使用 await 調用異步函數(shù):如果在調用異步函數(shù)時,不需要等待異步函數(shù)的返回結果,那么可以不適用 await關鍵字調用異步函數(shù)。
2、使用 Task.Run 來啟動異步操作:Task.Run 方法可以用來啟動一個新的異步操作,它會提供一個新的任務來異步函數(shù),從而避免了異步的傳遞性。
3、使用事件或回調來處理異步的結果:如果異步函數(shù)需要通知調用者操作已完成,可以使用事件或回調來代替直接的 await 調用。
4、將異步結果存放在變量中:如果需要等待異步操作的結果,但又不想立即等待它,可以將異步任務存儲在變量中,然后在需要訪問時使用 wait 方法來等待異步的完成。
好記性不然爛筆頭,在學習的路上留下點痕跡。希望能給大家?guī)韼椭?,也期待你的點贊和討論。
到此這篇關于談談對.NET中async/await的理解的文章就介紹到這了,更多相關.net async await內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Visual?Studio?2022常見的報錯以及處理方案圖文詳解
許多用戶在使用Visual Studio的過程中常會遇到各種問題,下面這篇文章主要給大家介紹了關于Visual?Studio?2022常見的報錯以及處理方案的相關資料,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2023-04-04Asp.net SignalR應用并實現(xiàn)群聊功能
這篇文章主要為大家分享了Asp.net SignalR應用并實現(xiàn)群聊功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04