在Windows 8里面很多API都封装成了异步的形式,因此异步编程成为了Windows 8的一大特色,同时也给Windows 8的应用更好的用户体验和简化了异步编程的复杂度。异步编程在Windows 运行时中是规范,而不是特例。JavaScript、C#、Visual Basic 和 C++ 都各自为异步方法提供了语言支持。
许多 Windows 运行时功能,如 MediaCapture 和 StorageFile,都被公开为异步函数。按照惯例,异步函数的名称以 "Async" 结尾,表示当调用已返回后可能会发生其部分执行。
当你在 Metro 风格应用中使用异步 API 时,你的代码将以一致的方式进行非阻止调用。当你在 API 中实现这些异步模式后,调用者可以理解并按照可预知的方式使用你的代码。
下面是一些需要调用异步 Windows 运行时 API 的常见任务。
显示消息对话框。
使用文件系统。
向 Internet 发送数据和从 Internet 接收数据。
有了 Windows 运行时异步 API 以后,你无需明确管理线程或直接与基础实现进行交互。
每种编程语言都按照其自己的方式支持异步模式:
编程语言
异步表示形式
JavaScript
承诺对象,then 函数
C#
将来对象,await 运算符
Microsoft Visual Basic .NET
将来对象,Await 运算符
Visual C++
task 类,.then 方法
下面来看一下一个获取网络信息的异步编程的例子
C#版本
UI
<Page
x:Class="AsyncDemo.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AsyncDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Button Content="获取网络信息" HorizontalAlignment="Left" Margin="114,280,0,0" VerticalAlignment="Top" Height="95" Width="210" Click="Button_Click_1"/>
<TextBlock x:Name="tb" HorizontalAlignment="Left" Margin="395,148,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Height="473" Width="878"/>
</Grid>
</Page>
CS页面
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Syndication;
namespace AsyncDemo
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
private async void Button_Click_1(object sender, RoutedEventArgs e)
Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
client.BypassCacheOnRetrieve = true;
Uri feedUri
= new Uri("http://feed.cnblogs.com/blog/sitehome/rss");
// 调用异步方法获取网络信息
SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);
//下面的代码在异步await 完成之后才开始执行 tb.Text = feed.Title.Text + Environment.NewLine;
foreach (SyndicationItem item in feed.Items)
{
tb.Text += item.Title.Text + ", " +
item.PublishedDate.ToString() + Environment.NewLine;
}
}
}
对异步方法 RetrieveFeedAsync 的调用,行 <code>SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri)</code> 使用 await 运算符。
假如使用的是同步方法的时候,UI会一直卡住一直等到网络请求完成之后才会释放掉UI的线程。但如果你调用 <code>client.RetrieveFeedAsync</code>,则方法启动检索并立即返回。当你将 await 与 RetrieveFeedAsync 结合使用时,应用临时退出事件处理程序。然后,它便可以在 RetrieveFeedAsync 异步执行时处理其他事件。 这样便可以保持应用对用户进行响应。 当 RetrieveFeedAsync 完成并且 SyndicationFeed 可用时,应用一定会在 <code>SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri)</code> 之后重新进入它停止的事件处理程序,并完成方法的剩余部分。
返回异步 API 的类型和结果
如果你跟随指向 RetrieveFeedAsync 的链接,那么你可能会注意到 RetrieveFeedAsync 的返回类型不是 SyndicationFeed。 返回类型为 <code>IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress></code> 。 异步 API 返回一个包含结果的对象。 尽管该对象很常见,但有时却很有用,若要将异步方法视为可等待的方法,await 运算符实际上对该方法的返回值执行操作,而不是对该方法执行操作。 当你应用 await 运算符时,可以获取异步方法的结果。
当使用异步方法时,你可以通过查看返回值来获取有关其结果的信息。 Windows 运行时中的所有异步 API 都返回以下类型之一:
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/br206598">IAsyncOperation<TResult></a>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/br206594">IAsyncOperationWithProgress<TResult, TProgress></a>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.foundation.iasyncaction">IAsyncAction</a>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/br206581">IAsyncActionWithProgress<TProgress></a>
下表给出了异步方法的示例并列出了每个方法的返回类型和结果类型。
异步方法
返回类型
结果类型
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.web.syndication.syndicationclient.retrievefeedasync">SyndicationClient.RetrieveFeedAsync</a>
IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.web.syndication.syndicationfeed">SyndicationFeed</a>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.applicationmodel.contacts.contactpicker.picksinglecontactasync">ContactPicker.PickSingleContactAsync</a>
IAsyncOperation<ContactInformation>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.applicationmodel.contacts.contactinformation">ContactInformation</a>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.data.xml.dom.xmldocument.savetofileasync">XmlDocument.SaveToFileAsync</a>
void
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.ui.input.inking.inkstrokecontainer.loadasync">InkStrokeContainer.LoadAsync</a>
IAsyncActionWithProgress<ulong>
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.storage.streams.randomaccessstream.copyasync">RandomAccessStream.CopyAsync</a>
IAsyncOperationWithProgress<ulong,ulong>
ulong
<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.storage.streams.datareader.loadasync">DataReader.LoadAsync</a>
uint
下面的是C++的版本
x:Class="AsyncDemoApp.MainPage"
xmlns:local="using:AsyncDemoApp"
h头文件
#pragma once
#include "MainPage.g.h"
namespace AsyncDemoApp
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public ref class MainPage sealed
public:
MainPage();
protected:
virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
private:
void Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
};
cpp
#include "pch.h"
#include <ppltasks.h >
#include "MainPage.xaml.h"
using namespace AsyncDemoApp;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace concurrency;
using namespace Windows::Web::Syndication;
MainPage::MainPage()
InitializeComponent();
}
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
(void) e; // Unused parameter
void AsyncDemoApp::MainPage::Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
String^ url = "http://feed.cnblogs.com/blog/sitehome/rss";
SyndicationClient^ client = ref new SyndicationClient();
auto feedOp = client->RetrieveFeedAsync(ref new Uri(url));
auto getNetInfoTask = create_task(feedOp);
getNetInfoTask.then([this](SyndicationFeed^ feed)
tb->Text = feed->Title->Text;
});
1调用 create_task 方法并将其传到 IAsyncOperation^ 对象。
运行的效果如下:
本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1078332