關于C#中async/await的用法實例詳解
一直對c#中async/await的用法模模糊糊,不太清晰,今天寫了一下Demo徹底明確一下async/await的用法,以免因為對其不了解而對后期的業(yè)務產生影響(比如事務導致的鎖表等等)。
1. 首先,async/await一般是成對出現(xiàn)才有意義。其意義在于可以等待異步操作完成后繼續(xù)順序執(zhí)行,而不是異步操作還沒處理完成主線程就進行了下一步。
假設,我們現(xiàn)在要模擬簡單的下載場景,首先用戶點擊下載,那么就調用DownloadHandle方法(異步)進行下載,然后通知用戶下載完成。其使用async/await的區(qū)別如下:
(1)使用async/await 的情況:
internal class Program { static void Main(string[] args) { DownloadHandle(); Console.ReadLine(); } /// <summary> /// 正常使用async/await時,符合正常的業(yè)務邏輯: /// 1. 通知用戶下載開始 /// 2. 異步下載 /// 3. 等待異步下載完成后給用戶提示下載完成 /// </summary> public static async void DownloadHandle() { Console.WriteLine("下載開始!->主線程ID:" + Thread.CurrentThread.ManagedThreadId); await Download(); Console.WriteLine("下載完成!->主線程ID:" + Thread.CurrentThread.ManagedThreadId); } /// <summary> /// 下載 /// </summary> /// <returns></returns> public static Task Download() { return Task.Run(() => { Console.WriteLine("下載線程ID:->" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("10%"); Console.WriteLine("30%"); Console.WriteLine("50%"); Console.WriteLine("60%"); Console.WriteLine("80%"); Console.WriteLine("99%"); Console.WriteLine("100%"); }); } }
結果如下:
可以看到,即時下載使用了異步(線程ID不同也表明了當前使用了異步),業(yè)務邏輯最終還是按照我們的需求,按順序正序執(zhí)行了。
(2)不使用async/await的情況:
internal class Program { static void Main(string[] args) { DownloadHandle(); Console.ReadLine(); } /// <summary> /// 不適用async/await時,則代碼執(zhí)行順序時混亂的,不符合業(yè)務邏輯: /// 1. 通知用戶下載開始 /// 2. 提示下載完成 /// 3. 開始下載 /// </summary> public static void DownloadHandle() { Console.WriteLine("下載開始!->主線程ID:" + Thread.CurrentThread.ManagedThreadId); Download(); Console.WriteLine("下載完成!->主線程ID:" + Thread.CurrentThread.ManagedThreadId); } /// <summary> /// 下載 /// </summary> /// <returns></returns> public static Task Download() { return Task.Run(() => { Console.WriteLine("下載線程ID:->" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("10%"); Console.WriteLine("30%"); Console.WriteLine("50%"); Console.WriteLine("60%"); Console.WriteLine("80%"); Console.WriteLine("99%"); Console.WriteLine("100%"); }); } }
結果如下:
可以看到,代碼執(zhí)行順序混亂了,“下載完成” 跑到了 “下載線程ID” 前面去了,完全沒有按照我們預期的順序執(zhí)行。
2. 如果可以await的方法不進行await,那將會怎樣呢?
(1)如果被調用的異步方法內部使用了Task.Run,那結果可參考我們1中進行講述的結果。開發(fā)者可根據實際需要來進行調用,如果異步方法的調用結果與其上下文邏輯沒有嚴格的執(zhí)行要求,則可以不進行await(比如記錄日志等等)。反之,則需要加await。
(2)如果被調用的異步方法內部只是返回了Task.CompletedTask,即時使用了await/async實際上還是等于同步執(zhí)行,如下圖。
internal class Program { static void Main(string[] args) { DownloadHandle(); Console.ReadLine(); } /// <summary> /// 模擬下載 /// </summary> public static async void DownloadHandle() { Console.WriteLine("下載開始!->主線程ID:" + Thread.CurrentThread.ManagedThreadId); await Download(); Console.WriteLine("下載完成!->主線程ID:" + Thread.CurrentThread.ManagedThreadId); } /// <summary> /// 下載 /// </summary> /// <returns></returns> public static Task Download() { Console.WriteLine("下載線程ID:->" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("10%"); Console.WriteLine("30%"); Console.WriteLine("50%"); Console.WriteLine("60%"); Console.WriteLine("80%"); Console.WriteLine("99%"); Console.WriteLine("100%"); return Task.CompletedTask; }
結果如圖:
可以看到,即使DonwloadHandle方法使用了await/async,還是進行了同步執(zhí)行,并沒有異步效果(可從所有線程ID相同看出)
3.小技巧: 異步方法的返回值類型一般都是Task或者Task<T>類型的,當返回值為Task時(即方法的返回值類型為void),我們可以直接return Task.Run(()=>{})(以下第一段代碼),而不必awaitTask.Run(()=>{})(以下第二段代碼),這樣也可從一定程度上提高代碼執(zhí)行效率。
/// <summary> /// 下載 /// </summary> /// <returns></returns> public static Task Download() { return Task.Run(() => { Console.WriteLine("下載線程ID:->" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("10%"); Console.WriteLine("30%"); Console.WriteLine("50%"); Console.WriteLine("60%"); Console.WriteLine("80%"); Console.WriteLine("99%"); Console.WriteLine("100%"); }); }
/// <summary> /// 下載 /// </summary> /// <returns></returns> public static async Task Download() { await Task.Run(() => { Console.WriteLine("下載線程ID:->" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("10%"); Console.WriteLine("30%"); Console.WriteLine("50%"); Console.WriteLine("60%"); Console.WriteLine("80%"); Console.WriteLine("99%"); Console.WriteLine("100%"); }); }
到此這篇關于關于C#中async/await的用法的文章就介紹到這了,更多相關C#中async/await的用法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#動態(tài)創(chuàng)建Access數(shù)據庫及表的方法
這篇文章主要介紹了C#動態(tài)創(chuàng)建Access數(shù)據庫及表的方法,以實例形式分析了創(chuàng)建access數(shù)據庫及在access數(shù)據庫中建表的完整過程,是非常實用的技巧,需要的朋友可以參考下2014-12-12C#實現(xiàn)微信結合百度api獲取當前用戶地理位置的方法
這篇文章主要介紹了C#實現(xiàn)微信結合百度api獲取當前用戶地理位置的方法,結合實例形式分析了C#調用微信與百度API接口的相關操作技巧,需要的朋友可以參考下2017-07-07c#實現(xiàn)一個超實用的證件照換底色小工具(附源碼)
這篇文章主要給大家介紹了關于利用c#實現(xiàn)一個超實用的證件照換底色小工具的相關資料,通過這個小工具大家可以很方便的進行底色的切換,不用再因為底色的原因頭疼了,需要的朋友可以參考借鑒,下面來一起學習學習吧。2018-01-01