天天看點

Windows 8 異步程式設計

在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&lt;SyndicationFeed, RetrievalProgress&gt;</code> 。 異步 API 傳回一個包含結果的對象。 盡管該對象很常見,但有時卻很有用,若要将異步方法視為可等待的方法,await 運算符實際上對該方法的傳回值執行操作,而不是對該方法執行操作。 當你應用 await 運算符時,可以擷取異步方法的結果。

當使用異步方法時,你可以通過檢視傳回值來擷取有關其結果的資訊。 Windows 運作時中的所有異步 API 都傳回以下類型之一:

<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/br206598">IAsyncOperation&lt;TResult&gt;</a>

<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/br206594">IAsyncOperationWithProgress&lt;TResult, TProgress&gt;</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&lt;TProgress&gt;</a>

下表給出了異步方法的示例并列出了每個方法的傳回類型和結果類型。

異步方法

傳回類型

結果類型

<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.web.syndication.syndicationclient.retrievefeedasync">SyndicationClient.RetrieveFeedAsync</a>

IAsyncOperationWithProgress&lt;SyndicationFeed, RetrievalProgress&gt;

<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&lt;ContactInformation&gt;

<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&lt;ulong&gt;

<a href="http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.storage.streams.randomaccessstream.copyasync">RandomAccessStream.CopyAsync</a>

IAsyncOperationWithProgress&lt;ulong,ulong&gt;

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  

    /// &lt;summary&gt; 

    /// An empty page that can be used on its own or navigated to within a Frame.  

    /// &lt;/summary&gt; 

    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 &lt;ppltasks.h &gt; 

#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-&gt;RetrieveFeedAsync(ref new Uri(url));  

    auto getNetInfoTask = create_task(feedOp);  

    getNetInfoTask.then([this](SyndicationFeed^ feed)   

              tb-&gt;Text = feed-&gt;Title-&gt;Text;  

        });  

1調用 create_task 方法并将其傳到 IAsyncOperation^ 對象。

運作的效果如下:

本文轉自linzheng 51CTO部落格,原文連結:http://blog.51cto.com/linzheng/1078332

繼續閱讀