async (C# 參考)async (C# Reference)

使用 async 修飾詞可將方法、Lambda 運算式匿名方法指定為非同步。Use the async modifier to specify that a method, lambda expression, or anonymous method is asynchronous. 如果您在方法或運算式上使用這個修飾詞,則它是指「非同步方法」。If you use this modifier on a method or expression, it's referred to as an async method. 下例定義名為 ExampleMethodAsync 的非同步方法:The following example defines an async method named ExampleMethodAsync:

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

如果您不熟悉非同步程式設計或不了解非同步方法如何使用 await 關鍵字進行可能需要長期執行的工作,而不封鎖呼叫端執行緒,請閱讀使用 async 和 await 進行非同步程式設計中的簡介。If you're new to asynchronous programming or do not understand how an async method uses the await keyword to do potentially long-running work without blocking the caller’s thread, read the introduction in Asynchronous Programming with async and await. 下列程式碼位於非同步方法中,會呼叫 HttpClient.GetStringAsync 方法:The following code is found inside an async method and calls the HttpClient.GetStringAsync method:

string contents = await httpClient.GetStringAsync(requestUrl);  

非同步方法會以同步方式執行,直到抵達第一個 await 運算式,此時方法會暫停,直到等候的工作完成。An async method runs synchronously until it reaches its first await expression, at which point the method is suspended until the awaited task is complete. 同時,控制項會返回方法的呼叫端,如下一節中的範例所示。In the meantime, control returns to the caller of the method, as the example in the next section shows.

如果 async 關鍵字修改的方法不包含 await 運算式或陳述式,則方法會以同步方式執行。If the method that the async keyword modifies doesn't contain an await expression or statement, the method executes synchronously. 如果有任何非同步方法未包含 await 陳述式,編譯器警告就會發出警示,因為這種情況可能表示發生錯誤。A compiler warning alerts you to any async methods that don't contain await statements, because that situation might indicate an error. 請參閱編譯器警告 (層級 1) CS4014See Compiler Warning (level 1) CS4014.

async 關鍵字與內容相關,它只有在修改方法、Lambda 運算式或匿名方法時,才是關鍵字。The async keyword is contextual in that it's a keyword only when it modifies a method, a lambda expression, or an anonymous method. 在所有其他內容中,它會解譯為識別項。In all other contexts, it's interpreted as an identifier.

範例Example

下列範例將示範非同步事件處理常式 StartButton_Click 與非同步方法 ExampleMethodAsync 之間的控制結構與流程。The following example shows the structure and flow of control between an async event handler, StartButton_Click, and an async method, ExampleMethodAsync. 非同步方法的結果是網頁的字元數。The result from the async method is the number of characters of a web page. 此程式碼適用於您在 Visual Studio 中建立的 Windows Presentation Foundation (WPF) 應用程式或 Windows 市集應用程式。請參閱有關設定應用程式的程式碼註解。The code is suitable for a Windows Presentation Foundation (WPF) app or Windows Store app that you create in Visual Studio; see the code comments for setting up the app.

您可以在 Visual Studio 中將此程式碼執行為 Windows Presentation Foundation (WPF) 應用程式或 Windows 市集應用程式。You can run this code in Visual Studio as a Windows Presentation Foundation (WPF) app or a Windows Store app. 您需要名為 StartButton 的按鈕控制項和名為 ResultsTextBox 的文字方塊控制項。You need a Button control named StartButton and a Textbox control named ResultsTextBox. 請記住要設定名稱和處理常式,如此才會有像下面這樣的內容:Remember to set the names and handler so that you have something like this:

<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 應用程式:To run the code as a WPF app:

  • 將此程式碼貼入 MainWindow.xaml.cs 的 MainWindow 類別。Paste this code into the MainWindow class in MainWindow.xaml.cs.
  • 將參考新增至 System.Net.Http。Add a reference to System.Net.Http.
  • 為 System.Net.Http 新增 using 指示詞。Add a using directive for System.Net.Http.

將程式碼執行為 Windows 市集應用程式:To run the code as a Windows Store app:

  • 將此程式碼貼入 MainPage.xaml.cs 的 MainPage 類別。Paste this code into the MainPage class in MainPage.xaml.cs.
  • 為 System.Net.Http 和 System.Threading.Tasks 新增 using 指示詞。Add using directives for System.Net.Http and System.Threading.Tasks.
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 進行非同步程式設計For more information about tasks and the code that executes while waiting for a task, see Asynchronous Programming with async and await. 如需使用類似項目的完整 WPF 範例,請參閱逐步解說:使用 async 和 await 存取 WebFor a full WPF example that uses similar elements, see Walkthrough: Accessing the Web by Using Async and Await.

傳回型別Return Types

非同步方法可有下列傳回型別:An async method can have the following return types:

  • Task
  • Task<TResult>
  • void,應該只用於事件處理常式。void, which should only be used for event handlers.
  • 自 C# 7.0 開始,任何具有可存取 GetAwaiter 方法的型別。Starting with C# 7.0, any type that has an accessible GetAwaiter method. System.Threading.Tasks.ValueTask<TResult> 類型就是一個這種實作。The System.Threading.Tasks.ValueTask<TResult> type is one such implementation. 新增 NuGet 套件 System.Threading.Tasks.Extensions 即可使用。It is available by adding the NuGet package System.Threading.Tasks.Extensions.

非同步方法不可宣告任何 inrefout 參數,也不可以有 參考傳回值,但可以呼叫有這類參數的方法。The async method can't declare any in, ref or out parameters, nor can it have a reference return value, but it can call methods that have such parameters.

如果方法的 return 陳述式指定 TResult 類型的運算元,請指定 Task<TResult> 作為非同步方法的傳回型別。You specify Task<TResult> as the return type of an async method if the return statement of the method specifies an operand of type TResult. 如果方法完成時未傳回任何有意義的值,則使用 TaskYou use Task if no meaningful value is returned when the method is completed. 也就是說,呼叫方法會傳回 Task,但是當 Task 完成時,等候 await 的任何 Task 運算式都會判斷值為 voidThat is, a call to the method returns a Task, but when the Task is completed, any await expression that's awaiting the Task evaluates to void.

您主要是使用 void 傳回類型定義需要該傳回類型的事件處理常式。You use the void return type primarily to define event handlers, which require that return type. 傳回 void 之非同步方法的呼叫端無法等候它,而且無法攔截方法擲回的例外狀況。The caller of a void-returning async method can't await it and can't catch exceptions that the method throws.

自 C# 7.0 開始,您會傳回另一個型別,通常是實值型別,具有 GetAwaiter 方法可將程式碼效能關鍵區段中的記憶體配置降至最低。Starting with C# 7.0, you return another type, typically a value type, that has a GetAwaiter method to miminize memory allocations in performance-critical sections of code.

如需詳細資訊和範例,請參閱非同步方法的傳回型別For more information and examples, see Async Return Types.

請參閱See Also

AsyncStateMachineAttribute
awaitawait
逐步解說:使用 Async 和 Await 存取 WebWalkthrough: Accessing the Web by Using Async and Await
使用 async 和 await 進行非同步程式設計Asynchronous Programming with async and await