1. 程式人生 > 其它 >C#——關鍵字:async

C#——關鍵字:async

技術標籤:C#c#

C#——關鍵字:async

async

使用 async 修飾符可將方法、lambda 表示式或匿名方法指定為非同步。 如果對方法或表示式使用此修飾符,則其稱為非同步方法 。 如下示例定義了一個名為 ExampleMethodAsync 的非同步方法:

public async Task<int> ExampleMethodAsync()
{
    //...
}

如果不熟悉非同步程式設計,或者不瞭解非同步方法如何在不阻止呼叫方執行緒的情況下使用 await 運算子執行可能需要長時間執行的工作,請參閱使用 Async 和 Await 的非同步程式設計中的說明。 如下程式碼見於一種非同步方法中,且呼叫 HttpClient.GetStringAsync 方法:

string contents = await httpClient.GetStringAsync(requestUrl);

非同步方法同步執行,直至到達其第一個 await 表示式,此時會將方法掛起,直到等待的任務完成。 同時,如下節示例中所示,控制元件將返回到方法的呼叫方。

如果 async 關鍵字修改的方法不包含 await 表示式或語句,則該方法將同步執行。 編譯器警告將通知你不包含 await 語句的任何非同步方法,因為該情況可能表示存在錯誤。 請參閱編譯器警告(等級 1)CS4014。

async 關鍵字是上下文關鍵字,原因在於只有當它修飾方法、lambda 表示式或匿名方法時,它才是關鍵字。 在所有其他上下文中,都會將其解釋為識別符號。

示例

下面的示例展示了非同步事件處理程式 StartButton_Click 和非同步方法 ExampleMethodAsync 之間的控制結構和流程。 此非同步方法的結果是 Web 頁面的字元數。 此程式碼適用於在 Visual Studio 中建立的 Windows Presentation Foundation (WPF) 應用或 Windows 應用商店應用;請參見有關設定應用的程式碼註釋。

可以在 Visual Studio 中將此程式碼作為 Windows Presentation Foundation (WPF) 應用或 Windows 應用商店應用執行。 需要一個名為 StartButton 的按鈕控制元件和一個名為 ResultsTextBox 的文字框控制元件。 切勿忘記設定名稱和處理程式,以便獲得類似於以下程式碼的內容:

<Button Content="Button" HorizontalAlignment="Left" Margin="88,77,0,0" VerticalAlignment="Top" Width="75"
        Click="StartButton_Click" Name="StartButton"/>
<TextBox HorizontalAlignment="Left" Height="137" Margin="88,140,0,0" TextWrapping="Wrap"
         Text="&lt;Enter a URL&gt;" VerticalAlignment="Top" Width="310" Name="ResultsTextBox"/>

將程式碼作為 WPF 應用執行:

1.將此程式碼貼上到 MainWindow.xaml.cs 中的 MainWindow 類中。
2.新增對 System.Net.Http 的引用。
3.為 System.Net.Http 新增一個 using 指令。

將此程式碼作為 Windows 應用商店應用執行:

1.將此程式碼貼上到 MainPage.xaml.cs 中的 MainPage 類中。
2.為 System.Net.Http 和 System.Threading.Tasks 新增 using 指令。
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // ExampleMethodAsync returns a Task<int>, which means that the method
    // eventually produces an int result. However, ExampleMethodAsync returns
    // the Task<int> value as soon as it reaches an await.
    ResultsTextBox.Text += "\n";

    try
    {
        int length = await ExampleMethodAsync();
        // Note that you could put "await ExampleMethodAsync()" in the next line where
        // "length" is, but due to when '+=' fetches the value of ResultsTextBox, you
        // would not see the global side effect of ExampleMethodAsync setting the text.
        ResultsTextBox.Text += String.Format("Length: {0:N0}\n", length);
    }
    catch (Exception)
    {
        // Process the exception if one occurs.
    }
}

public async Task<int> ExampleMethodAsync()
{
    var httpClient = new HttpClient();
    int exampleInt = (await httpClient.GetStringAsync("http://msdn.microsoft.com")).Length;
    ResultsTextBox.Text += "Preparing to finish ExampleMethodAsync.\n";
    // After the following return statement, any method that's awaiting
    // ExampleMethodAsync (in this case, StartButton_Click) can get the
    // integer result.
    return exampleInt;
}
// The example displays the following output:
// Preparing to finish ExampleMethodAsync.
// Length: 53292

重要

若要深入瞭解各項任務以及在等待任務期間所執行的程式碼,請參閱使用 Async 和 Await 的非同步程式設計。 有關使用類似元素的完整控制檯示例,請參閱在非同步任務完成時對其進行處理 (C#)

返回型別

非同步方法可具有以下返回型別:

1.Task
2.Task<TResult>
3.void。 對於除事件處理程式以外的程式碼,通常不鼓勵使用 async void 方法,因為呼叫方不能 await 那些方法,並且必須實現不同的機制來報告成功完成或錯誤條件。
4.從 C# 7.0 開始,任何具有可訪問的 GetAwaiter 方法的型別。 System.Threading.Tasks.ValueTask<TResult> 型別屬於此類實現。 它通過新增 NuGet 包 System.Threading.Tasks.Extensions 的方式可用。

此非同步方法既不能宣告任何 in、ref 或 out 引數,也不能具有引用返回值,但它可以呼叫具有此類引數的方法。

如果非同步方法的 語句指定一個 型別的運算元,則應指定 Task 作為方法的返回型別TResult。 如果當方法完成時未返回有意義的值,則應使用 Task。 即,對方法的呼叫將返回一個 Task,但是當 Task 完成時,任何等待 await 的所有 Task 表示式的計算結果都為 void。

你應主要使用 void 返回型別來定義事件處理程式,這些處理程式需要此返回型別。 void 返回非同步方法的呼叫方不能等待,並且無法捕獲該方法引發的異常。

從 C# 7.0 開始,返回另一個型別(通常為值型別),該型別具有 GetAwaiter 方法,可儘可能減少效能關鍵程式碼段中的記憶體分配。
有關詳細資訊和示例,請參閱非同步返回型別