快速入门:使用 C# 或 Visual Basic 调用异步 API

Windows 运行时包含许多异步 API,目的是确保你的应用在执行可能需要大量时间的任务时仍能保持响应。 这就意味着你的应用无需等待大规模操作完成即可继续执行。 例如,从 Internet 下载信息的应用等待信息到达可能要花费数秒钟。如果你使用同步方法来检索信息,则应用会在方法返回之前被阻止。应用将不会响应用户交互,而且因为无响应的原因,所以用户可能会感到沮丧。 通过提供异步 API,Windows 运行时有助于确保你的应用在执行较长的操作时仍能保持对用户进行响应。

Windows 运行时中的大多数异步 API 都没有对应的同步 API,因此你需要确保了解如何在 Windows 运行时应用中一同使用异步 API 与 C# 或 Visual Basic。下面将显示如何调用 Windows 运行时的异步 API。

路线图: 本主题与其他主题有何关联?请参阅:

先决条件

请参阅创建你的第一个使用 C# 或 Visual Basic 的 Windows 运行时应用

使用异步 API

按照惯例,异步方法的名称应以“"Async"”结尾。通常调用异步 API 是为了响应用户的操作,如用户单击某个按钮时。 在事件处理程序中调用异步方法是使用异步 API 的最简单方法之一。 下面使用 await 运算符作为一个示例。

假设你拥有一个应用,该应用列出了某个位置中博客文章的标题。 该应用具有一个 Button,用户单击该按钮即可获取标题。 标题显示在 TextBlock中。 当用户单击该按钮时,该应用仍然保持响应,同时等待获取博客文章的信息,这一点非常重要。 为了确保此响应,Windows 运行时提供了一个用于下载源的异步方法 SyndicationClient.RetrieveFeedAsync

以下示例通过调用异步方法 SyndicationClient.RetrieveFeedAsync 从一个博客获取博客文章列表。这是调用异步方法的最简单方法。


// Put the keyword, async on the declaration of the event handler.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{

    Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();

    // Force the SyndicationClient to download the information.
    client.BypassCacheOnRetrieve = true;

    Uri feedUri
        = new Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");

    try
    {
        // Call SyndicationClient RetrieveFeedAsync to download the list of blog posts.
        SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

        // The rest of this method executes after await RetrieveFeedAsync completes.
        rssOutput.Text = feed.Title.Text + Environment.NewLine;

        foreach (SyndicationItem item in feed.Items)
        {
            rssOutput.Text += item.Title.Text + ", " +
                             item.PublishedDate.ToString() + Environment.NewLine;
        }
    }
    catch (Exception ex)
    {
        // Log Error.
        rssOutput.Text =
            "I'm sorry, but I couldn't load the page," +
            " possibly due to network problems." +
            "Here's the error message I received: "
            + ex.ToString();
    }
}


有关该示例,有几个重要事项。首先,对异步方法 RetrieveFeedAsync 的调用,行 SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) 使用 await 运算符。你可以将 await 运算符视为告知编译器你正在调用某个异步方法,该方法会导致编译器执行某些额外的工作,以便你无需进行这些工作。接下来,事件处理程序的声明包含关键字 async。你必须将该关键字包含在其中使用 await 运算符的任何方法的方法声明中。这与需要 async 关键字的 Button.Click 事件处理程序签名无关;特意添加了 async,以便编译器将允许从处理程序的主体调用异步方法。有关处理输入事件和在其中运行 awaitable 方法的详细信息,请参阅事件和路由事件概述

在本主题中,我们将不对编译器使用 await 运算符所执行的操作进行详细介绍,而是检查一下你的应用所执行的操作以便该操作是异步操作并且能够响应。 考虑使用同步代码时发生的情况。 例如,假设有一个名为 SyndicationClient.RetrieveFeed 的异步方法。 (不存在这样的方法,但想象存在这样的方法。) 如果你的应用包含了行 SyndicationFeed feed = client.RetrieveFeed(feedUri),而不是一直执行应用的 SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) 直到返回值 RetrieveFeed 可用为止。 当你的应用等待方法完成时,它无法响应任何其他事件,如另一个 Click 事件。 即,你的应用将被阻止,直到 RetrieveFeed 返回为止。

但如果你调用 client.RetrieveFeedAsync,则方法启动检索并立即返回。当你将 awaitRetrieveFeedAsync 结合使用时,应用临时退出事件处理程序。然后,它便可以在 RetrieveFeedAsync 异步执行时处理其他事件。 这样便可以保持应用对用户进行响应。 当 RetrieveFeedAsync 完成并且 SyndicationFeed 可用时,应用一定会在 SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) 之后重新进入它停止的事件处理程序,并完成方法的剩余部分。

有关使用 await 运算符的好处是代码看上去与使用想象的 RetrieveFeed 方法的代码并没有很多不同。 可以在不使用 await 运算符的情况下,采用 C# 或 Visual Basic 编写异步代码,但所得到的代码通常会强调异步执行的机制。这使得异步代码难以编写、理解和维护。通过使用 await 运算符,你可以获得异步应用的优势,同时又不会使代码复杂。

返回异步 API 的类型和结果

如果你跟随指向 RetrieveFeedAsync 的链接,那么你可能会注意到 RetrieveFeedAsync 的返回类型不是 SyndicationFeed, 而是 IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>。 从原始语法看,异步 API 返回其中包含结果的对象。 尽管该对象很常见,但有时却很有用,若要将异步方法视为可等待的方法,await 运算符实际上对该方法的返回值执行操作,而不是对该方法执行操作。 当你应用 await 运算符时,可以获取异步方法的结果。 尤其是,你会获得对在原始语法中看到的对象调用 GetResult 的结果。在该示例中,SyndicationFeed 就是 RetrieveFeedAsync 的结果。

当使用异步方法时,你可以通过查看返回值来获取有关其结果的信息。 Windows 运行时中的所有异步 API 都返回以下类型之一:

异步方法的结果类型与 TResult 类型参数相同。 没有 TResult 的类型没有结果。 你可以将结果视为 void。 在 Visual Basic 中,Sub 过程等同于返回类型为 void 的方法。

下表给出了异步方法的示例并列出了每个方法的返回类型和结果类型。

异步方法返回类型结果类型
SyndicationClient.RetrieveFeedAsync IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> SyndicationFeed
FileOpenPicker.PickSingleFileAsync IAsyncOperation<StorageFile> StorageFile
XmlDocument.SaveToFileAsync IAsyncAction void
InkStrokeContainer.LoadAsync IAsyncActionWithProgress<UInt64> void
DataReader.LoadAsync DataReaderLoadOperation,实现 IAsyncOperation<UInt32> 的自定义结果类。 UInt32

 

.NET for Windows Runtime apps 中定义的异步方法的返回类型为 TaskTask<TResult>。 返回 Task 的方法与 Windows 运行时中返回 IAsyncAction 的异步方法类似。 在任何情况下,异步方法的结果都为 void。 返回类型 Task<TResult> 类似于 IAsyncOperation<TResult>,因为在运行任务时,异步方法的结果与 TResult 类型参数的类型相同。 有关使用 .NET for Windows Runtime apps 和任务的详细信息,请参阅用于 Windows 运行时应用的 .NET 概述

处理错误

当你使用 await 运算符从异步方法检索结果时,可以使用一个 try/catch 块来处理异步方法中发生的错误,与处理同步方法中的错误一样。 上一个示例将 RetrieveFeedAsync 方法和 await 操作包装到一个 try/catch 块中,以便在引发异常时处理错误。

当异步方法调用其他异步方法时,所有引发异常的异步方法都将被传播到外部方法。 这意味着你可以将一个 try/catch 块放在最外层的方法中,以便为嵌套异步方法捕获错误。这同样与你为同步方法捕获异常的方式类似。然而,你不能在 catch 块中使用 await

摘要和后续步骤

下面我们介绍的调用异步方法的模式就是在事件处理程序中调用异步 API 时使用的最简单方法。 当在返回 void 或 Visual Basic 中的 Sub 的替代方法中调用异步方法时,也可以使用此模式。

当你遇到 Windows 运行时中的异步方法时,需要记住以下几点:

  • 按照惯例,异步方法的名称应以“"Async"”结尾。
  • 所有使用 await 运算符的方法都必须使用 async 关键字对其声明进行标记。
  • 当应用查找 await 运算符时,应用仍然响应用户交互,并且同时执行异步方法。
  • 异步方法返回一个包含其结果的对象。 多数情况下,返回值的结果非常有用,而不是返回值本身。 你可以通过查看返回类型来查找结果类型。
  • 使用异步 API 和 async 模式通常是提高应用性能的一种方法。有关使用异步 API 提高性能的详细信息,请参阅保持 UI 线程响应;该主题专门讨论了实现逻辑作为 Task,以便它是异步的。

本主题中的示例所输出的文本如下所示:

Windows Experience Blog
PC Snapshot: Sony VAIO Y, 8/9/2011 10:26:56 AM -07:00
Tech Tuesday Live Twitter #Chat: Too Much Tech #win7tech, 8/8/2011 12:48:26 PM -07:00
Windows 7 themes: what’s new and what’s popular!, 8/4/2011 11:56:28 AM -07:00
PC Snapshot: Toshiba Satellite A665 3D, 8/2/2011 8:59:15 AM -07:00
Time for new school supplies? Find back-to-school deals on Windows 7 PCs and Office 2010, 8/1/2011 2:14:40 PM -07:00
Best PCs for blogging (or working) on the go, 8/1/2011 10:08:14 AM -07:00
Tech Tuesday – Blogging Tips and Tricks–#win7tech, 8/1/2011 9:35:54 AM -07:00
PC Snapshot: Lenovo IdeaPad U460, 7/29/2011 9:23:05 AM -07:00
GIVEAWAY: Survive BlogHer with a Sony VAIO SA and a Samsung Focus, 7/28/2011 7:27:14 AM -07:00
3 Ways to Stay Cool This Summer, 7/26/2011 4:58:23 PM -07:00
Getting RAW support in Photo Gallery & Windows 7 (…and a contest!), 7/26/2011 10:40:51 AM -07:00
Tech Tuesdays Live Twitter Chats: Photography Tips, Tricks and Essentials, 7/25/2011 12:33:06 PM -07:00
3 Tips to Go Green With Your PC, 7/22/2011 9:19:43 AM -07:00
How to: Buy a Green PC, 7/22/2011 9:13:22 AM -07:00
Windows 7 themes: the distinctive artwork of Cheng Ling, 7/20/2011 9:53:07 AM -07:00

相关主题

使用 C# 或 Visual Basic 的 Windows 运行时应用的路线图
基于任务的异步模式 (TAP) - 白皮书
Reversi 示例功能方案:异步代码

 

 

显示:
© 2015 Microsoft