天天看點

第十五節:深入了解async和await的作用及各種适用場景和用法

I. 同步 VS 異步

1. 同步 VS 異步 VS 多線程

同步方法:您需要等待結果傳回後才能繼續執行業務

異步方法:您可以繼續執行業務,而無需等待調用時傳回結果

打開新線程:在主線程外部打開新線程以執行業務

同步方法和異步方法之間的本質差別:是否需要在調用時等待結果傳回,然後才能繼續業務

2. 常見的異步方法(全部以異步結尾)

(1) httpClient 類:PostAsync、 Putasync、 GetAsync、 Deleteasync

(2) EF 中的 DbContext 類:儲存更改異步

(3) 檔案相關:寫線異步

第十五節:深入了解async和await的作用及各種适用場景和用法

3. 介紹異步方法的背景

例如,我想從背景另一台伺服器的2個接口擷取資訊,然後将兩個接口的資訊拼接在一起并輸出在一起,接口1取3s,接口2取5s,

(1) 傳統同步:

所需時間約為:3s 和 5s,如下所示,案例 1

首先共享同步請求接口的封裝方法,如下所示。

然後對共享服務進行耗時的操作,一樣。

下面是案例 1 代碼

第十五節:深入了解async和await的作用及各種适用場景和用法

(2) 打開新線程需要兩個耗時的操作

所需時間約為:最大(3s,5s)s 5s,如下面的案例2所示

第十五節:深入了解async和await的作用及各種适用場景和用法

由于(2)方法可以解決同步方法中串行耗時的問題,是以這種方法存在一個缺點,即一個業務中存在多個線程,并且需要管理線程,相對繁瑣,進而導緻異步方法。

我的意思是異步方法:系統類庫附帶的異步方法,以異步結尾。

(3) 使用系統類庫附帶的異步方法

所需時間約為:最大(3 秒、5 秒),如下所示,案例 3

第十五節:深入了解async和await的作用及各種适用場景和用法

PS: 通過 .執行異步方法後擷取結果的結果。

使用異步和等待的異步方法的封裝

1. 第一個陳述是幾點:

(1)異步和 await 關鍵字是在 C# 5.0 時代引入的,這是一種異步程式設計模型

(2)他們自己不建立新線程,但我可以使用Task.Run在我自己的封裝異步中打開新線程

(3)如果用異步關鍵字封裝的方法全是序列槽業務,并且不使用 await 關鍵字,那麼即使使用異步封裝,也沒有蛋使用,也不起異步方法的作用。

所需時間約為:3s 和 5s s 8s,如下面的案例 4 所示,封裝的方法編譯器将提示:"缺少的關鍵字 await 将被同步調用,請使用 await 運算符等待非阻塞 API 或 Task.Run 的形式"(PS:非阻塞 API 是指以 Async 結尾的系統類庫附帶的異步方法)

第十五節:深入了解async和await的作用及各種适用場景和用法

結論1:從上述(3)可以得出結論,異步必須有等待運算符扮演異步方法的角色,而等待運算符隻能添加到系統類庫中預設提供的異步方法或新線程(例如Task.Run)。

例如:以下案例 5 和 6 所需的時間約為:最大(3 秒、5 秒)

第十五節:深入了解async和await的作用及各種适用場景和用法
第十五節:深入了解async和await的作用及各種适用場景和用法

2. 若幹規則和慣例

(1) 在 async 封裝的方法中,可以有多個 await,其中 await 代表等待代碼行執行。

(2)我們通常封裝自己的方法也以異步結束,以便于識别

(3)異步傳回主要有三種類型:Task<T>、Task、Void

3. 測試得出了其他幾個結論

(1)如果由異步封裝的異步方法同時具有同步和異步業務(打開新線程或系統類庫提供異步方法),則該部分同步方法的時間将在調用時阻塞主線程,即主線程将不得不等待這部分同步業務執行下來,然後再執行下來。

例如,案例7 耗時:同步操作2s加2s加最大(3s,5s)s 9s的總和;

第十五節:深入了解async和await的作用及各種适用場景和用法

證明:異步封裝的異步方法中的同步時間阻止了主線程,再次證明隻能在非阻塞API和打開新線程之前添加等待

(2) 如果封裝的異步方法中存在等待問題,主線程無法被阻塞(無法使用 Thread.Sleep),此時可以使用 Task.Delay,更早添加 await 關鍵字

例如,案例 8:最大 (2-3, 5-2) -7s

第十五節:深入了解async和await的作用及各種适用場景和用法

異步方法傳回類型

1. 任務< T>,通過 處理包含傳回值的異步方法。Result 等待異步方法完成并擷取傳回值。

2. 任務:調用方法不需要從異步方法擷取傳回值,但如果要檢查異步方法的狀态,可以選擇可以傳回 Task 類型的對象。但是,即使異步方法包含 return 語句,也不會傳回任何内容。

例如 案例9

第十五節:深入了解async和await的作用及各種适用場景和用法

PS:對于Task傳回值的異步方法,您可以調用Wait(),并且當異步方法完成時,與 await不同,await必須出現在由async關鍵字封裝的方法中。

3. void:調用異步執行方法,無需任何互動

例如 案例10

第十五節:深入了解async和await的作用及各種适用場景和用法

若幹結論

1. 異步方法是否打開新線程?

異步和等待關鍵字不會導緻建立其他線程。由于異步方法本身不線上程上運作,是以異步方法不需要多個線程。僅當方法處于活動狀态時,該方法才會在目前同步上下文中運作并使用線程上的時間。可以使用 Task.Run 将 CPU 工作移動到背景線程,但背景線程不利于等待結果可供處理。(摘自MSDN原文)

2. 異步和 await 是異步程式設計模型,它們本身不會打開新線程,而是用于封裝不阻塞 API 或打開新線程的操作,以便像同步方法一樣調用它們。

下面補充部落格花園嘟嘟說明,友善大家了解。

第十五節:深入了解async和await的作用及各種适用場景和用法