http://www.cnblogs.com/linzheng/archive/2012/07/03/2574039.html 在Windows 8里面很多API都封裝成了異步的形式,因此異步編程成為了Windows 8的一大特色,同時也給Windows 8的應用更好的用戶體驗和簡化了異步編程的復雜度。異步編程在Windows 運行時中是規范,而不是特例。JavaScript、C#、Visual Basic 和 C++ 都各自為異步方法提供了語言支持。
許多 Windows 運行時功能,如 MediaCapture 和 StorageFile,都被公開為異步函數。按照慣例,異步函數的名稱以 "Async" 結尾,表示當調用已返回后可能會發生其部分執行。
當你在 Metro 風格應用中使用異步 API 時,你的代碼將以一致的方式進行非阻止調用。當你在 API 中實現這些異步模式后,調用者可以理解并按照可預知的方式使用你的代碼。
下面是一些需要調用異步 Windows 運行時 API 的常見任務。
有了 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 的調用,行 SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) 使用 await 運算符。
假如使用的是同步方法的時候,UI會一直卡住一直等到網絡請求完成之后才會釋放掉UI的線程。但如果你調用 client.RetrieveFeedAsync,則方法啟動檢索并立即返回。當你將 await 與 RetrieveFeedAsync 結合使用時,應用臨時退出事件處理程序。然后,它便可以在 RetrieveFeedAsync 異步執行時處理其他事件。 這樣便可以保持應用對用戶進行響應。 當 RetrieveFeedAsync 完成并且 SyndicationFeed 可用時,應用一定會在 SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) 之后重新進入它停止的事件處理程序,并完成方法的剩余部分。
返回異步 API 的類型和結果
如果你跟隨指向 RetrieveFeedAsync 的鏈接,那么你可能會注意到 RetrieveFeedAsync 的返回類型不是 SyndicationFeed。 返回類型為 IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> 。 異步 API 返回一個包含結果的對象。 盡管該對象很常見,但有時卻很有用,若要將異步方法視為可等待的方法,await 運算符實際上對該方法的返回值執行操作,而不是對該方法執行操作。 當你應用 await 運算符時,可以獲取異步方法的結果。
當使用異步方法時,你可以通過查看返回值來獲取有關其結果的信息。 Windows 運行時中的所有異步 API 都返回以下類型之一:
異步方法的結果類型與 TResult 類型參數相同。 沒有 TResult 的類型沒有結果。 你可以將結果視為 void。 在 Visual Basic 中,Sub 過程等同于返回類型為 void 的方法。
下表給出了異步方法的示例并列出了每個方法的返回類型和結果類型。
.NET for Metro style apps 中的異步方法的返回類型為 Task 或 Task<TResult>。 返回 Task 的方法與 Windows 運行時中返回 IAsyncAction 的異步方法類似。 在任何情況下,異步方法的結果都為 void。 同樣,返回類型 Task<TResult> 類似于 IAsyncOperation<TResult>,因為異步方法的結果與 TResult 類型參數的類型相同。
下面的是C++的版本
UI
<Page
x:Class="AsyncDemoApp.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AsyncDemoApp"
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>

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;
});
}

在 C++ 中直接使用異步 Windows 運行時 API,首選方法是使用 task class 及其相關類型和函數,它們都包含在 concurrency 命名空間中且在 ppltasks.h 中定義。
利用任務類來使用返回 IAsyncOperation 接口且其操作會生成一個值的異步方法,步驟如下:
1調用 create_task 方法并將其傳到 IAsyncOperation^ 對象。
2調用任務上的成員函數 task::then 并且提供一個將在異步操作完成時調用的 lambda。
task::then 方法立即返回,并且其委派直至異步工作成功完成后才運行。
運行的效果如下:
