簡體   English   中英

為什么我們必須在 C# 中等待異步方法調用

[英]Why do we have to await an async method call in C#

在 C# 中,當我們調用異步方法時,需要在方法內等待它,否則編譯器會發出警告消息說該方法將被稱為同步而沒有“等待”。 我知道這在以下情況下很有用:

var task = DoSomethingLongAsync();
DoSomethingElse();
await task;

那是因為當我們調用該異步方法時,我們可以做其他事情,然后等待異步結果。

但在其他一些情況下,我們不需要等待異步結果,比如類似於 web 服務器的場景:

listen();
while (true)
{
    var request = Accept();
    await ProcessRequestAsync(request);
}

顯然,對於上述場景,我們希望請求可以並行處理。 但是如果我們在那里使用 await (作為當前的),請求將被一一處理,而不是我們預期的那樣。

那么在類似的場景中我們應該如何調用異步方法呢?

不必使用await - 這是一個警告,而不是錯誤。
編譯器給你這個警告是因為async方法的通常用例是異步運行它們,為此,你使用await關鍵字。

基本上,此警告是編譯器提醒您注意的方式,以確保不會忽視 go - 但它不會阻止您在沒有await關鍵字的情況下使用async方法 - 您的代碼將編譯並運行。

如果您可以查看此文檔,則可以看到:

await 運算符不會阻塞評估異步方法的線程。

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/await

所以如果你不想阻塞你的線程。 你應該使用等待。 這就是我們異步設計方法的方式!

如果您將方法設計為異步並在沒有等待的情況下調用它。 這意味着你應該得到警告:)

正如@Zohar Peled 所寫,這只是一個警告。

寫下以下內容,讓別人清楚你的意圖。

換句話說,只需丟棄生成的任務,因為在這種情況下它與您無關。

listen();
while (true)
{
    var request = Accept();
    _ = ProcessRequestAsync(request);
}

大多數時候,不等待異步方法調用完全沒問題。

您可以只接受生成的任務,並將其保留以備后用

var requestTask = ProcessRequestAsync(request);

或者獲取一組任務然后等待它們全部完成,它們將並行工作

var task1 = ProcessRequestAsync(request1);
var task2 = ProcessRequestAsync(request2);
var task3 = ProcessRequestAsync(request3);

await Task.WhenAll(new [] { task1, task2, task3 });

或者只是第一個,在其他人還在工作的時候用它做點什么。

await Task.WhenAny(new [] { task1, task2, task3 });

您不必等待其中任何一個,只要您的應用程序仍在運行,任務就會運行並完成。

如果您厭倦了看到這些編譯器警告,您可以告訴 VS 忽略它們。

#pragma warning disable 4014
service.DoSomethingAsync();
#pragma warning restore 4014

我通常發現這些警告很有幫助,所以我只在不需要等待它們完成的“即發即棄”異步調用中禁用它們(例如,日志記錄)。

暫無
暫無

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

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