C 中 async 和 await 的基本使用

2022-09-07 17:15:21 字數 2694 閱讀 5613

經常在 c# 的**中看到以async結尾的方法,大概知道意為非同步方法,但不知道怎麼使用,也不知道如何定義。

對於「同步」、「非同步」、「阻塞」、"非阻塞"這幾個概念還是比較清楚的。同步是指等待方法的執行完成;非同步是指設定方法執行後繼續其它操作,通過**的方式對結果進行其它操作;阻塞是指執行到這一步就不往後了,直到執行完成;非阻塞是指執行這一步時,還可以進行其它操作。

這兩組概念其實是講的乙個東西,只是針對的方向有些許區別(乙個強調是否立即返回,乙個強調是否繼續往後)

對於 c# 中的 async 和 await,可以這麼簡單理解:async 告訴 runtime,這個函式可以非同步去執行以提高效率。await 則告訴 runtime,真正耗時的是在我這個關鍵字後面的操作。

本文僅希望在使用的層面驗證,對於原理以及是否新開執行緒等,由於能力有限,暫不深入

對於本地環境而言,讀取大檔案是比較耗時的操作之一。因此先寫乙個讀取檔案的操作,再用 async 和 await 的方法將其包裹,以**這兩個關鍵字的使用(為了模擬執行一番後得到最後的結果,我們返回二進位制檔案的最後乙個位元組所代表的數字)。

1. 初步**,同步呼叫耗時方法

using system;

using system.io;

namespace asyncawaittest

/// /// 讀取大檔案(耗時方法)

可以看出,耗時約 10 s。

2. 使用非同步關鍵字包裹同步方法

新增函式 asynccallreadlargefile,並修改 main 函式中的呼叫。通過查閱資料可以得知,task 類的 result 方法在執行時會阻塞

using system;

using system.io;

using system.threading.tasks;

namespace asyncawaittest

/// /// 使用非同步關鍵字包裹同步方法

///

///

private static async taskasynccallreadlargefile()

/// /// 讀取大檔案(耗時方法)

小結:通過耗時可以明顯看出:

(1)我們的非同步方法確實是以非同步的方式執行了(對同一檔案進行三個非同步讀操作,耗時沒有疊加)

(2)大致的執行順序如**注釋中所示,也即,使用 await 時,確實等待執行完成當前後才會執行非同步函式中後續的方法

(3)即使在非同步函式中,未用 await 修飾的方法也是同步執行的(通過截圖無法看出,但通過觀察**輸出可以看出)

1. 非同步的方法最終會由同步方法呼叫

這句話看上去有點絕對了,但確實是這個道理。從寫法上:寫函式時,有 async 就必須有 await(否則會警告,並且以同步方式執行),有 await 就必須有 async(否則會報錯),而非同步函式必須要使用這兩個成對出現的關鍵字。從道理上:非同步方法就是來解決同步方法順序執行過於循規蹈矩問題的,沒有同步方法的呼叫怎麼會有這些問題呢?

2. async,await 和 task 什麼關係

嘗試過這一種寫法:

/* 錯誤寫法 */

private static async byte asynccallreadlargefile()

錯誤 cs1061 「byte」未包含「getawaiter」的定義,並且找不到可接受第乙個「byte」型別引數的可訪問擴充套件方法「getawaiter」(是否缺少 using 指令或程式集引用?)

似乎可以認為,只有返回的型別包含 getawaiter 的定義,才能被當作非同步函式來呼叫。最常見的只有 task 包含這個方法。想到之前看到過,async 修飾的函式,返回型別只能是 void, task, task

3. 非同步方法的返回

在 asynccallreadlargefile 函式中,雖然簽名中返回型別是 task,但我們實際上只返回了 byte 型別,並沒有 task。我的理解是對於 async 修飾的非同步方法,返回的型別會自動被包裝成 task 的泛型型別。

深入理解async和await的作用及各種適用場景和用法(舊,詳見最新兩篇)

c# 徹底搞懂async/await

(這兩篇都很全面,受益匪淺)

C 中的Async 和 Await 的用法詳解

自從c 5.0時代引入async和await關鍵字後,非同步程式設計就變得流行起來。尤其在現在的.net core時代,如果你的 中沒有出現async或者await關鍵字,都會讓人感覺到很奇怪。想象一下當我們在處理ui和按鈕單擊時,我們需要執行乙個長時間執行的方法,比如讀取乙個大檔案或其他需要很長時...

async和await的講解

普通的函式宣告 async function a 複製 宣告乙個函式表示式 let a async function 複製 async形式的箭頭函式 let a async 複製 async與await例項應用,基礎 控制器呼叫與server中查詢資料 exports.getbloglist asy...

async和await的使用

async其實是es7的才有的,是非同步操作的進化,其實就是封裝乙個promise的物件返回 async function test console.log test promiseasync方法在普通的函式前加上 async 關鍵字即可。執行這個函式,發現並沒有返回1111,而是通過promise...