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. 此异步方法的结果是 Web 页面的字符数。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.

如果异步方法的 语句指定一个 类型的操作数,则应指定 Task<TResult> 作为方法的返回类型TResultYou 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 minimize memory allocations in performance-critical sections of code.

有关详细信息和示例,请参阅异步返回类型For more information and examples, see Async Return Types.

请参阅See also