使用 Async 和 Await 的异步编程

异步方法容易编写

string urlContents = await client.GetStringAsync();

如下特征总结了使上面一个异步方法。

  • 方法签名包含一个 Asyncasync 修饰符。html

  • 异步方法的名称以“Async”后缀,按照约定,关闭。编程

  • 返回类型为下列类型之一:c#

    • Task<TResult>,若是您的方法具备操做个线程类型 TResult 的返回语句。windows

    • Task,若是方法没有返回语句或具备返回语句不操做。多线程

    • 无效 (在 Visual Basic 中 ),若是您编写一个异步事件处理程序。架构

  • 方法一般包含至少一个等待表达式,指示个方法没法继续,直到该等待的异步操做完成的。同时,方法被挂起,而且,控件返回到方法的调用方。本主题的下一节将解释发生的悬挂点。app

       在异步方法,可使用提供的关键字和类型指示要执行,所以,编译器执行方式,包括记录必须出现,当控件处于挂起的方法时回时间点。某些实例处理,例如循环,而异常处理,可能很难进行在传统异步代码的句柄。在异步方法,解决您编写这些元素,由于在一个同步解决方案会并将问题。异步

任何异步方法

           若要了解的最重要的操做在异步编程是控制流如何从方法移动到方法。下图经过处理致使生成。async

           

在关系图的数值对应于如下步骤。 异步编程

说明:

  1. 事件处理程序调用并等待 AccessTheWebAsync 异步方法。

  2. AccessTheWebAsync 建立HttpClient 实例并调用GetStringAsync 异步方法下载网站内容做为字符串。

  3. 挂起团队进度的内容发生 GetStringAsync 发生。 可能必须等待网站下载或一些其余块的事件。若要避免妨碍资源,GetStringAsync 为控件对其调用方,AccessTheWebAsync

    GetStringAsync返回 TResult 是字符串的Task<TResult>,而且,AccessTheWebAsync 将任务指派给getStringTask 变量。在工做完成时,任务表示继续对定向到GetStringAsync,以提交致使实际字符串值。

  4. 因为 getStringTask 不等待,AccessTheWebAsync 能够继续执行不依赖于从 GetStringAsync的最终结果的其余工做。 该任务由为同步方法DoIndependentWork的调用表示。

  5. DoIndependentWork 完成其工做并回调用方的同步方法。

  6. AccessTheWebAsync 用完了它能够完成,不会受到getStringTask的结果的工做。接下来AccessTheWebAsync 若要计算并返回该下载的字符串的长度,可是,该方法没法计算该值,直到该方法具备字符串。

    所以,AccessTheWebAsync 使用一个等待运算符挂起的进度并使控件到调用AccessTheWebAsync的方法。AccessTheWebAsync 返回Task(Of Integer)Task<int> 调用方。任务表示形式致使为下载的字符串的长度的整数结果。 (说明:若是GetStringAsync (并 getStringTask) 后,在AccessTheWebAsync 等待以前,控件在AccessTheWebAsync保持。成本挂起而后返回到AccessTheWebAsync 将浪费,若是异步调用过程 (getStringTask) 已经完成了,而且 AccessTheWebSync 没必要等待最终结果。      在调用方 (在此示例中的事件处理程序内),处理重复。调用方可能完成不依赖于从AccessTheWebAsync 的结果在等待该结果以前的其余工做,或调用方可能当即等待。在事件处理程序到达等待表达式时,应用程序集中精力GetStringAsync的完成。事件处理程序等待AccessTheWebAsync,而且,AccessTheWebAsync 等待GetStringAsync

  7. GetStringAsync完成并生成一个字符串结果。字符串结果不经过对GetStringAsync 的调用返回方式与您可能指望的。(请确保方法返回已在第 3 步 .) 的任务,字符串结果在表示方法的完成的任务,getStringTask存储。等待运算符从getStringTask检索结果。赋值语句将检索的结果赋给urlContents

  8. GetStringAsync完成并生成一个字符串结果。字符串结果不经过对GetStringAsync 的调用返回方式与您可能指望的。(请确保方法返回已在第 3 步 .) 的任务,字符串结果在表示方法的完成的任务,getStringTask存储。等待运算符从getStringTask检索结果。赋值语句将检索的结果赋给urlContents

           若是您不熟悉异步编程,请须要一分钟考虑同步和异步行为之间的差别。一个同步方法返回,其工做完成 (第 5 步),可是,异步方法返回任务值,其工做挂起时 (第 3 步和第 6 步)。在异步方法最终完成其工做时,任务将会标记为已完成和结果,若是有,在任务中。

API 异步方法         

          在什么状况下可能想知道找到支持异步编程的方法 (如GetStringAsync.NET Framework 4.5 包含与异步以及等待的许多成员。您能够经过附加到成员名称和TaskTask<TResult>的返回类型“Async”后缀识别这些成员。例如,System.IO.Stream 选件类包含方法例如CopyToAsyncReadAsyncWriteAsync 在同步方法CopyToReadWrite

       Windows 运行时 还包含您在 Windows 应用商店 apps 可使用异步和等待的许多方法。

线程

          异步方法旨在成为非阻塞操做。当等待的任务运行时,在异步方法的一个等待表达式不会阻止当前线程。相反,该表达式注册该方法的其他部分做为继续并返回控制对异步方法的调用方。

          异步和等待关键字不会致使其余线程建立。由于异步方法自己并不会运行的线程,异步方法不须要多线程。只有 + 当方法处于活动状态,则方法在当前同步上下文中运行并使用在线程的时间。可使用Task.Run 移动 CPU 工做移到后台线程,可是,后台线程不利于等待结果变得可用处理。

       以异步编程的基于异步的方法优于于几乎每一个用例的现有方法。具体而言,此方法比 IO 操做的BackgroundWorker 好,由于代码更为简单的,所以无需防止争用条件。Task.Run的组合,异步编程的 CPU 操做的BackgroundWorker 好,由于异步编程从Task.Run 传输到线程池的工做分隔运行您的代码以协调详细信息。

异步和等待

若是指定使用 异步异步 修饰符,方法是异步方法,能够实现如下两个函数。

  • 清单异步方法可使用 Await 或指定的 等待 悬挂点。等待运算符通知编译器异步方法不能继续点的过去,直到等待的异步过程完成。同时,控制权交还异步方法的调用方。

    一个异步方法的备用在等待表达式的不构成从方法的退出,而且,finally 块不会运行。

  • 清单异步方法自己能够经过调用它的方法等待。

       异步方法一般包含等待运算符的一个或多个匹配项,可是,请假等待表达式不会致使编译器错误。若是异步方法不会将等待运算符指示悬挂点,方法尽管"修饰符执行,一个同步方法。编译器会发出此类方法的警告。

          AsyncasyncAwaitawait 是上下文关键字。

返回类型和参数

           在编程 .NET framework,异步方法一般返回TaskTask<TResult>在异步方法中,等待运算符应用于从调用返回到另外一个异步方法的任务。

           您指定 Task<TResult>,由于返回类型,则方法包含指定类型TResult操做上的一个返回 (Visual Basic) 或返回 (c#) 语句。

使用 Task,由于返回类型,则该方法没有返回语句或具备不返回操做线程的 return 语句。

        下面的示例演示如何声明并调用返回Task<TResult>Task的方法。

// Signature specifies Task<TResult> async Task<int> TaskOfTResult_MethodAsync() { int hours; // . . . // Return statement specifies an integer result. return hours; } // Calls to TaskOfTResult_MethodAsync Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync(); int intResult = await returnedTaskTResult; // or, in a single statement int intResult = await TaskOfTResult_MethodAsync(); // Signature specifies Task async Task Task_MethodAsync() { // . . . // The method has no return statement. } // Calls to Task_MethodAsync Task returnedTask = Task_MethodAsync(); await returnedTask; // or, in a single statement await Task_MethodAsync();

        每一个返回的任务表示正在进行的工做。任务封装有关状态的信息异步过程和,最后,从进程的最终结果或处理引起的异常;若是未成功。

        异步方法也是 Sub 方法 (Visual Basic) 或使 void 返回类型 (c# 中)。这将返回类型主要用于定义事件处理程序,void 返回类型须要。异步事件处理程序一般用做异步程序的起始点。

        是 Sub 程序或具备 void 返回类型不能等待的异步方法和一个无效返回的方法的调用方没法捕获方法引起的任何异常。

        异步方法不能声明在 Visual Basic 或refByRef 参数或在 C# 中http://msdn.microsoft.com/zh-cn/library/t3c3bfhx.aspx 参数,可是,方法能够调用具备这些参数的方法。

在 Windows 运行时 编程的异步 API 使之一返回类型,相似于任务:

命名约定

          按照约定,您追加“Async”传递给具备Asyncasync 修饰符方法的名称。

       您能够忽略事件、基类或接口协定建议一个不一样的名称约定。例如,您不该向经常使用事件处理程序重命名,例如Button1_Click

相关主题

标题

描述

示例

演练:使用 Async 和 Await 访问 Web(C# 和 Visual Basic)

演示如何将同步 WPF 解决方法转换为异步 WPF 解决方案。 应用程序下载一系列网站。

Async 示例:访问 Web 演练 (C# 和 Visual Basic)

如何:使用 Task.WhenAll 扩展演练(C# 和 Visual Basic)

添加 Task.WhenAll 到上一个演练中。使用WhenAll 启动同时下载。

如何:并行发起多个 Web 请求(C# 和 Visual Basic)

演示如何同时启动几个任务。

Async 示例:并行生成多个 Web 请求 (C# 和 Visual Basic)

异步返回类型(C# 和 Visual Basic)

描述异步方法可能会返回的类型并解释每一个类型时正确。

异步程序中的控制流(C# 和 Visual Basic)

跟踪控制流在连续详细在等待异步程序的表达式。

Async 示例:在异步程序的控制流 (C# 和 Visual Basic)

微调异步应用程序(C# 和 Visual Basic)

演示如何添加如下功能添加到的"解决方法:

Async 示例:优化应用程序 (C# 和 Visual Basic)

处理异步应用程序中的重入(C# 和 Visual Basic)

演示如何有效的异步操做从新启动的处理种状况下,在运行时。

WhenAny:.NET Framework 和 Windows 运行时之间的桥接(C# 和 Visual Basic)

演示如何消除在任务之间 .NET framework 和 IAsyncOperations 在 Windows 运行时,以即可以使用WhenAny 与 Windows 运行时 方法。

Async 示例:它们在 .NET 和窗口运行时 (AsTask 和 WhenAny)

取消:.NET Framework 和 Windows 运行时之间的桥接(C# 和 Visual Basic)

演示如何消除在任务之间 .NET framework 和 IAsyncOperations 在 Windows 运行时,以即可以使用CancellationTokenSource 与 Windows 运行时 方法。

Async 示例:它们在 .NET 和窗口运行时 (AsTask &取消)

使用 Async 以进行文件访问(C# 和 Visual Basic)

列出并演示如何使用异步的优势并等待访问文件。

演练:将调试器与异步方法一块儿使用

演示在等待语句的控制流,并演示 单步执行逐过程跳出 命令的行为在异步方法中。

基于任务的异步模式 (TAP)

描述 .NET framework 中 asynchrony 的新架构。 该模式根据 TaskTask<TResult> 类型。

快速入门:调用 c# 或 Visual Basic 中的异步 API

在 Windows 应用商店 app 演示如何使用异步和等待。

异步编程 (windows 存储 apps)

提供异步编程的概述 Windows 运行时。

在通道 9 的"视频

提供指向有关异步编程的各类视频。

完整的示例

          下面的代码是从本主题讨论的 windows 演示基础 (WPF) 应用程序的 MainWindow.xaml.vb 或 MainWindow.xaml.cs 文件。可下载示例从Async 示例:从“异步编程的示例使用"和”等待

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; // Add a using directive and a reference for System.Net.Http; using System.Net.Http; namespace AsyncFirstExample { public partial class MainWindow : Window { // Mark the event handler with async so you can use await in it. private async void StartButton_Click(object sender, RoutedEventArgs e) { // Call and await separately. //Task<int> getLengthTask = AccessTheWebAsync(); //// You can do independent work here. //int contentLength = await getLengthTask; int contentLength = await AccessTheWebAsync(); resultsTextBox.Text += String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); } // Three things to note in the signature: // - The method has an async modifier. // - The return type is Task or Task<T>. (See "Return Types" section.) // Here, it is Task<int> because the return statement returns an integer. // - The method name ends in "Async." async Task<int> AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task<string>. That means that when you await the // task you'll get a string (urlContents). Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); // You can do work here that doesn't rely on the string from GetStringAsync. DoIndependentWork(); // The await operator suspends AccessTheWebAsync. // - AccessTheWebAsync can't continue until getStringTask is complete. // - Meanwhile, control returns to the caller of AccessTheWebAsync. // - Control resumes here when getStringTask is complete. // - The await operator then retrieves the string result from getStringTask. string urlContents = await getStringTask; // The return statement specifies an integer result. // Any methods that are awaiting AccessTheWebAsync retrieve the length value. return urlContents.Length; } void DoIndependentWork() { resultsTextBox.Text += "Working . . . . . . .\r\n"; } } } // Sample Output: // Working . . . . . . . // Length of the downloaded string: 41564.

转载自:http://msdn.microsoft.com/zh-cn/library/hh191443.aspx   (中文地址)

                http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx (英文地址) 中文翻译的太烂了,若是英语不差的话,建议看英文。