簡體   English   中英

async 方法是否應該始終調用 await,如果不是,這意味着什么?

[英]Should async method always call await, if not what is the implication?

在這個例子中,

private async void Button1_Click(object sender, EventArgs e)
{
    if (condition) await Task.Run(Foo);
}

private void Foo()
{
    Thread.Sleep(5000);
}

有時條件為假,異步方法什么都不等待。 但是考慮這個例子,

private async void Button1_Click(object sender, EventArgs e)
{
    await Task.Run(Foo);
}

private void Foo()
{
    if (condition) Thread.Sleep(5000);
}

總是等待該方法的地方,即使條件為假。 我想知道幕后發生了什么,如果一個比另一個更可取,我的意思是客觀地,如果有編譯器優化使一個比另一個更可取。 假設可以從任何線程檢查條件,並且對性能的影響非常小。

似乎當條件檢查被推遲時,總是有一個任務正在等待,但是當它在處理程序中為 false 時,我的情況接近於異步方法缺少 await 運算符的情況,編譯器警告我. 所以它同時感覺是錯誤的和正確的。 希望有人能客觀地闡明這個問題。

async 方法是否應該始終調用 await,如果不是,這意味着什么?

正如我在我的博客中所描述的, async方法總是同步開始執行,就像任何其他方法一樣。 await是事情可能變得異步的地方。

如果采用沒有await的代碼路徑(或者如果等待的任務已經完成),則該方法同步完成並將已完成的任務返回給其調用者。 這在實踐中不是問題,因為“*Async”意味着“可能是異步的”,而不是“必須是異步的”。

在此特定示例中,您使用的是async void ,但如果這是一個被多次調用的async Task方法,在這種情況下我建議考慮返回ValueTask ,這將在任務完成時為Task節省一些 memory 分配同步地。

該方法上的async關鍵字只是向編譯器指示,該方法內的代碼應轉換為狀態機,在await時具有 state 次轉換。

據我所知,擁有一個不await任何東西的async方法的唯一技術缺點是狀態機引入的少量開銷。 它應該沒有負面影響,除了非常小的性能影響和一點點內存壓力,這在您的場景中很可能會被忽略。

在您的特定情況下Thread.Sleep(5000)不是暫停執行的最佳方式。 Thread.Sleep(5000)是一個舊的 API,它會在給定時間(5000 毫秒)內阻塞執行線程。 這是什么意思 這意味着該線程將無法用於其他任務。 比方說,給定您的計算機 CPU output,您總共有 4 個線程,您將其中 1 個線程鎖定 5000 毫秒——這真的很糟糕,尤其是如果它是一個 web 應用程序,它必須處理並發的 API 個請求。 用什么代替? await Task.Delay(5000)它將“掛起”給定時間的執行,但線程將返回線程池並將可用於其他任務。

現在更接近你的問題了。 將非異步代碼包裝到Task並等待不會做任何事情。 Async/await 專為 I/O 操作而設計,專門用於不阻塞等待 I/O 完成的線程。 將代碼包裝到Task而不等待- 基本上是“即發即忘”,這意味着您的執行線程可能會繼續執行下一個塊,而無需等待您的Task方法完成。 為什么我說可能是因為如果你在Task中的代碼包裝器足夠快它會同步工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM