共用方式為


WhenAny:銜接 .NET Framework 和 Windows 執行階段 (C# 和 Visual Basic)

本主題中的範例合併下載網誌饋送非同步與 .NET Framework 方法處理非同步工作順序完成的 Windows 執行階段 型別。 如需型別的詳細資訊,請 SyndicationClient參閱。 如需方法的詳細資訊,請參閱 Task.WhenAny

您可以結合這些功能,您可以啟動同時下載多個網誌饋送和處理結果,在完成。 如果一個摘要比其他快速下載,其結果會先出現。 使用 SyndicationClient 方法,您可以更輕鬆地下載摘要;使用 Task.WhenAny 方法,您可以更輕鬆地識別完成下載下摘要。

注意事項注意事項

若要執行這個範例,必須在電腦上安裝 Windows 8。此外,因此,如果您要從 Visual Studio 執行這個範例,您也必須在 Visual Studio 2012 已安裝或 Visual Studio Express 2012 for Windows 8

下列程式碼會將 Windows 執行階段 和 .NET Framework的下列功能:

Try
    Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
        From uri In uriList
        Select client.RetrieveFeedAsync(uri).AsTask()
    ' AsTask changes the returns from RetrieveFeedAsync into tasks.

    ' Run the query to start all the asynchronous processes.
    Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()

    Dim feed As SyndicationFeed

    ' Repeat the following until there are no tasks left:
    '    - Grab the first one that finishes.
    '    - Retrieve the results from the task (what the return statement 
    '      in RetrieveFeedAsync returns).
    '    - Remove the task from the list.
    '    - Display the results.
    While blogFeedTasksList.Count > 0
        Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
        feed = Await nextTask
        blogFeedTasksList.Remove(nextTask)
        DisplayResults(feed)
    End While

Catch ex As Exception
    ResultsTextBox.Text =
        "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
End Try
try
{
    IEnumerable<Task<SyndicationFeed>> feedsQuery =
            from uri in uriList
            // AsTask changes the returns from RetrieveFeedAsync into tasks.
            select client.RetrieveFeedAsync(uri).AsTask();

    // Run the query to start all the asynchronous processes.
    List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();

    SyndicationFeed feed;

    // Repeat the following until no tasks remain:
    //    - Grab the first one that finishes.
    //    - Retrieve the results from the task (what the return statement 
    //      in RetrieveFeedAsync returns).
    //    - Remove the task from the list.
    //    - Display the results.
    while (blogFeedTasksList.Count > 0)
    {
        Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
        feed = await nextTask;                    
        blogFeedTasksList.Remove(nextTask);
        DisplayResults(feed);
    }
}
catch (Exception ex)
{
    ResultsTextBox.Text =
        "Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
}

這個範例會產生類似下列的輸出。 對於每個網誌,顯示標題和日期之後的部落格上的標題部落格文章的。

Developing for Windows
     New blog for Windows 8 app developers, 5/1/2012 2:33:02 PM -07:00
     Trigger-Start Services Recipe, 3/24/2011 2:23:01 PM -07:00
     . . .
     Countdown to PDC10, 10/26/2010 4:11:28 PM -07:00

Extreme Windows Blog
     PDXLAN 20: “Epidemic” Custom PC by Jon Hansz, 7/30/2012 2:31:35 PM -07:00
     Samsung Notebook Series 9: Taking Thin and Light to the Extreme, 7/23/2012 12:06:03 PM -07:00
     . . .
     AMD Unveils A-Series APUs, 6/13/2011 9:34:01 PM -07:00

Blogging Windows
     Windows 8 has reached the RTM milestone, 8/1/2012 9:00:00 AM -07:00
     Windows 8 will be available on…, 7/18/2012 1:09:00 PM -07:00
     . . .
     More buzz from BUILD – Developers get their devices!, 9/13/2011 7:47:57 PM -07:00

Springboard Series Blog
     What to Expect in User Experience Virtualization Beta 2, 6/25/2012 11:03:27 PM -07:00
     Introducing Microsoft BitLocker Administration 2.0 Beta, 6/12/2012 8:08:23 AM -07:00
     . . .
     The Springboard Series Visits Lima, Peru, 11/18/2011 5:27:37 AM -08:00

本主題的其餘部分的相關詳細資料建置範例,以及如何運作。

您必須在電腦和 Windows 8 安裝的 Visual Studio 2012 執行此應用程式。

本主題包含下列章節。

  • 範例的設定選項。
  • 了解起始程式碼
  • 擴充起始程式碼
  • 下載起始程式碼
  • 下載完成的應用程式
  • 建立起始程式碼
  • 建置完成的應用程式
  • 相關主題

範例的設定選項。

這個範例會根據所描述 快速入門:使用非同步程式設計的 Await 運算子的部落格讀取器。 不過,本主題的起始程式碼下載多個網誌饋送 (而不是一個。

起始程式碼使用 Windows 執行階段 功能循序下載網誌饋送。 即網誌饋送依照 URL 的集合清單的順序下載。 完成的應用程式從 .NET Framework 將功能下載網誌饋送到完成的命令。

您可以將範例程式碼用以下幾種方式:

  • 起始程式碼。

    • 您可以依照 下載起始程式碼中的指示下載起始程式碼,

    • 您可以依照 建立起始程式碼中的指示建立起始程式碼。

    • 您可以檢閱起始程式碼,而不需要實作它捲動到 建立起始程式碼。

  • 完成的應用程式。

    • 您可以依照 下載完成的應用程式中的指示下載完成的應用程式

    • 您可以依照指示建置應用程式在 建置完成的應用程式。

    • 您可以檢閱完成的應用程式,而不需要實作它捲動到 建置完成的應用程式。

了解起始程式碼 一節中這個基本的討論金鑰。

擴充起始程式碼 一節會說明如何透過將 AsTaskTask.WhenAny修改程式碼。

了解起始程式碼

起始程式碼使用 SyndicationClient 方法, RetrieveFeedAsync,下載從每個 URI 的網誌饋送在 URI 的清單。 每次呼叫方法傳回代表進行中的非同步作業的 IAsyncOperationWithProgress 執行個體。 當等候,非同步作業產生包含下載的網誌饋送的資訊的 SyndicationFeed 執行個體。

程式碼會定義套用 RetrieveFeedAsync 至 URI 清單的每個項目的查詢。 執行時,查詢傳回 IAsyncOperationWithProgress 執行個體的集合。

Dim feedsQuery As IEnumerable(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                                RetrievalProgress)) =
                                                From uri In uriList
                                                Select client.RetrieveFeedAsync(uri)
IEnumerable<IAsyncOperationWithProgress<SyndicationFeed, 
    RetrievalProgress>> feedsQuery = from uri in uriList
                                     select client.RetrieveFeedAsync(uri);

如下列程式碼所示,ToList<TSource> 會執行查詢並開始非同步處理序。

Dim blogFeedOpsList As List(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                           RetrievalProgress)) =
                                               feedsQuery.ToList()
List<IAsyncOperationWithProgress<SyndicationFeed, 
    RetrievalProgress>> blogFeedOpsList = feedsQuery.ToList();

現在,您有作用中的 IAsyncOperationWithProgress 執行個體的清單。 您仍然必須等候每個執行個體取得最終結果。

下列迴圈等候每個 IAsyncOperationWithProgress 執行個體擷取 SyndicationFeed 結果。

Dim feed As SyndicationFeed
For Each blogFeedOp In blogFeedOpsList
    ' The Await operator retrieves the final result (a SyndicationFeed instance)
    ' from each IAsyncOperation instance.
    feed = Await blogFeedOp
    DisplayResults(feed)
Next
SyndicationFeed feed;
foreach (var blogFeedOp in blogFeedOpsList)
{
    // The await operator retrieves the final result (a SyndicationFeed instance)
    // from each IAsyncOperation instance.
    feed = await blogFeedOp;
    DisplayResults(feed);
}

您可以檢閱程式的這個版本中的 Building the Starter Code 區段內設定本主題結尾。

您可以找到有關程式設計的詳細資訊與 快速入門:使用非同步程式設計的 Await 運算子非同步 Windows 執行階段 API。

擴充起始程式碼

起始程式碼,示範 SyndicationClient 可下載網誌饋送。 完成這個範例中的其餘步驟會讓應用程式處理網誌饋送到下載完成而非命令它們出現在 URI 清單的命令。

對完成增強的索引鍵是 Task.WhenAny 方法。 當您將 WhenAny 套用至非同步處理序的集合時,方法會傳回第一個完成的程序,使您必須等候的時間。 在此範例中,部落格摘要資訊出現的順序並不重要。 如果下載緩慢,從其他部落格上的結果可能會先顯示。 這種情況似乎完善對 WhenAny 除了一件事: WhenAny 需要的工作集合。

JJ635140.collapse_all(zh-tw,VS.110).gif叫用 AsTask

WhenAny 需要 TaskTask<TResult> 執行個體的集合,不過,下載部落格上的 SyndicationClient 方法將會傳回的 IAsyncOperationWithProgress 執行個體。 因此,應用程式必須橋接在與 Windows 執行階段 的 IAsyncOperationWithProgress 物件和 .NET Framework 的 Task 物件之間。

.NET Framework 提供 AsTask 擴充方法進行轉換。 當您叫用在 IAsyncOperationWithProgress 執行個體的 AsTask 傳回 AsTask ,表示非同步作業的工作。 工作完成時,對應的 IAsyncOperationWithProgress 執行個體完成,因此,工作會執行個體的結果或例外狀況。

因此,您對 RetrieveFeedAsync 傳回,如下列程式碼顯示的每個 IAsyncOperationWithProgress 執行個體的 AsTask 。 程式碼給變數以反映對工作所做的變更並使用明確為了清楚起見輸入。

Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
    From uri In uriList
    Select client.RetrieveFeedAsync(uri).AsTask()
' AsTask changes the returns from RetrieveFeedAsync into tasks.

' Run the query to start all the asynchronous processes.
Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()
IEnumerable<Task<SyndicationFeed>> feedsQuery =
        from uri in uriList
        // AsTask changes the returns from RetrieveFeedAsync into tasks.
        select client.RetrieveFeedAsync(uri).AsTask();

// Run the query to start all the asynchronous processes.
List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();
注意事項注意事項

AsTask 在非同步程式設計中扮演重要角色可能不知道。編譯器會使用 AsTask ,每當您將 Await 運算子對 IAsyncAction 或 IAsyncOperation 執行個體,,如下列程式碼所示。

JJ635140.collapse_all(zh-tw,VS.110).gif套用 WhenAny

最後一個步驟中轉換會將 Task.WhenAny 方法加入至應用程式。 WhenAny 套用至工作 (blogFeedTasksList) 和傳回的集合會在完成集的第一個工作。 具體來說,就是 WhenAny ,傳回,當等候,評估為工作必須先完成的工作。

下列陳述式呼叫 WhenAny 並等候結果。 程式碼使用更清楚顯示結果的明確型別。

Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);

下列程式碼的作用與上一個陳述式,但是中斷相同作業加入至兩個陳述式裡釐清發生的事情。 第一個陳述式呼叫,則為 WhenAny,而第二個陳述式等候結果。

' WhenAny returns a task that, when awaited, produces a task.
' Call:
Dim whenAnyTask As Task(Of Task(Of SyndicationFeed)) = Task.WhenAny(blogFeedTasksList)
' Await:
Dim nextTask As Task(Of SyndicationFeed) = Await whenAnyTask
// WhenAny returns a task that, when awaited, produces a task.
// Call:
Task<Task<SyndicationFeed>> whenAnyTask = Task.WhenAny(blogFeedTasksList);
// Await:
Task<SyndicationFeed> nextTask = await whenAnyTask;

最後,您必須等候 nextTask 從先完成的工作擷取結果 ( SyndicationFeed 執行個體),您必須從清單中移除 nextTask ,以便您不再處理它。

feed = Await nextTask
blogFeedTasksList.Remove(nextTask)
feed = await nextTask;                    
blogFeedTasksList.Remove(nextTask);

使用 while 迴圈執行每項工作的步驟在 blogFeedTasksList。

While blogFeedTasksList.Count > 0
    Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
    feed = Await nextTask
    blogFeedTasksList.Remove(nextTask)
    DisplayResults(feed)
End While
while (blogFeedTasksList.Count > 0)
{
    Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
    feed = await nextTask;                    
    blogFeedTasksList.Remove(nextTask);
    DisplayResults(feed);
}

您可以檢閱程式的這個版本中的 建置完成的應用程式 區段內設定本主題結尾。 或者您可以按照 下載完成的應用程式 中的指示下載專案。

警告

使用迴圈的 WhenAny ,如本範例所說明,可正常是涉及少量工作的問題。不過,因此,如果您需要處理,大量工作其他方法會更有效率。如需詳細資訊和範例,請 管理工作,這些工作完成參閱。

下載起始程式碼

您可以下載範例的起始程式碼。 Async 範例:從 .NET 的橋接至視窗 如果您無法存取網際網路,請依照 建立起始程式碼 中的指示本主題結尾建立起始程式碼。

在您下載程式碼之後,已開啟且會執行下列步驟來執行。

  1. 解壓縮您下載的檔案,然後啟動 Visual Studio 2012。

  2. 在功能表列上,選擇 [檔案]、[開啟]、[專案/方案]。

  3. 巡覽至保存解壓縮的範例程式碼的資料夾,然後開啟 AsTaskWhenAnyDemoVB 或 AsTaskWhenAnyDemoCS 的方案 (.sln) 檔。

  4. 在 [方案總管] 中,開啟 [SequentialBlogReader] 專案的捷徑功能表,然後選擇 [做為啟始專案的集合]。

  5. 選擇 F5 鍵建置及執行專案。

  6. 執行程式碼幾次驗證結果相同順序每次出現。

您可以檢閱 建立起始程式碼 區段的 MainPage.xaml.vb 或 MainPage.xaml.cs 檔案在這個主題的結尾。

這個範例會根據所描述 快速入門:使用非同步程式設計的 Await 運算子的部落格讀取器。 不過,本主題的起始程式碼下載多個網誌饋送 (而不是一個。

如需可對應用程式各個改善和擴充的詳細資訊,請參閱 建立部落格讀取器

下載完成的應用程式

如果您不要建立這個範例,您可以下載完整範例。 請依照 下載起始程式碼 一節中的指示,不過,選取 [WhenAnyBlogReader] 為 [啟始專案]。

執行程式幾次驗證網誌饋送出現在不同的命令。

您可以檢閱 建置完成的應用程式 區段的 MainPage.xaml.vb 或 MainPage.xaml.cs 檔案在這個主題的結尾。

建立起始程式碼

您可以下載本主題中的範例。 Async 範例:從 .NET 的橋接至視窗 如果您想要設定您的應用程式,請遵循下列步驟。

  1. 啟動 Visual Studio 2012。

  2. 在功能表列上,選擇 [檔案]、[新增]、[專案]。

    [新增專案] 對話方塊隨即開啟。

  3. 在 [安裝] 中, [ [範本] 分類中,選取 [Visual Basic] 或 [Visual C#]],然後選取專案類型清單中的 [Windows 市集] 。

  4. 在專案類型清單中,選取 [空白的應用程式 (XAML)]。

  5. 將專案命名為 SequentialBlogReader,然後選擇 [OK] 按鈕。

    新專案即會出現於 [方案總管] 中。

  6. 在 [方案總管] 中,開啟 MainPage.xaml 的捷徑功能表,然後選擇 [開啟]。

  7. 在 [XAML] 視窗中 MainPage.xaml,以下列程式碼取代程式碼。

    <Page
        x:Class="SequentialBlogReader.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AsTaskWhenAnyDemo"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Stretch" Margin="325,128,330,0" VerticalAlignment="Top" Click="StartButton_Click" Height="71" Background="#FFA89B9B" FontWeight="Bold" FontSize="36"/>
            <TextBox x:Name="ResultsTextBox" Margin="325,222,330,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" />
        </Grid>
    </Page>
    

    包含文字方塊和按鈕的簡易視窗會出現在 [設計] 視窗中 MainPage.xaml。

    如需可對 UI 的各種改善和擴充的詳細資訊,請參閱 建立部落格讀取器

  8. 在 [方案總管] 中,開啟或 MainPage.xaml.vb MainPage.xaml.cs 的捷徑功能表,然後選擇 [檢視程式碼]。

  9. 使用下列程式碼取代或 MainPage.xaml.vb MainPage.xaml.cs 的程式碼。

    ' Add an Imports statement for SyndicationClient.
    Imports Windows.Web.Syndication
    
    
    ' The Blank Page item template is documented at http:'go.microsoft.com/fwlink/?LinkId=234238
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
    
        End Sub
    
    
        ' The async modifier enables you to use await in the event handler.
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ResultsTextBox.Text = ""
    
            ' Disable the button until the operation is complete.
            StartButton.IsEnabled = False
    
            Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()
    
            ' Force the SyndicationClient to download the information.
            client.BypassCacheOnRetrieve = True
    
            Dim uriList = CreateUriList()
    
            Try
                Dim feedsQuery As IEnumerable(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                                                RetrievalProgress)) =
                                                                From uri In uriList
                                                                Select client.RetrieveFeedAsync(uri)
    
                ' Run the query to start all the asynchronous processes.
                Dim blogFeedOpsList As List(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                                           RetrievalProgress)) =
                                                               feedsQuery.ToList()
    
                Dim feed As SyndicationFeed
                For Each blogFeedOp In blogFeedOpsList
                    ' The Await operator retrieves the final result (a SyndicationFeed instance)
                    ' from each IAsyncOperation instance.
                    feed = Await blogFeedOp
                    DisplayResults(feed)
                Next
    
            Catch ex As Exception
                ResultsTextBox.Text =
                    "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
            End Try
    
            ' Reenable the button in case you want to run the operation again.
            StartButton.IsEnabled = True
        End Sub
    
    
        Function CreateUriList() As List(Of Uri)
    
            ' Create a list of URIs.
            Dim uriList = New List(Of Uri) From
            {
                    New Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
            }
            Return uriList
        End Function
    
    
        Sub DisplayResults(sf As SyndicationFeed)
    
            ' Title of the blog.
            ResultsTextBox.Text &= sf.Title.Text & vbCrLf
    
            ' Titles and dates for blog posts.
            For Each item As SyndicationItem In sf.Items
    
                ResultsTextBox.Text &= vbTab & item.Title.Text & ", " &
                                    item.PublishedDate.ToString() & vbCrLf
            Next
    
            ResultsTextBox.Text &= vbCrLf
        End Sub
    End Class
    
    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;
    
    // Add a using directive for SyndicationClient.
    using Windows.Web.Syndication;
    
    
    namespace SequentialBlogReader
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                ResultsTextBox.Text = "";
    
                // Disable the button until the operation is complete.
                StartButton.IsEnabled = false;
    
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
    
                // Force the SyndicationClient to download the information.
                client.BypassCacheOnRetrieve = true;
    
                var uriList = CreateUriList();
    
                try
                {
                    IEnumerable<IAsyncOperationWithProgress<SyndicationFeed, 
                        RetrievalProgress>> feedsQuery = from uri in uriList
                                                         select client.RetrieveFeedAsync(uri);
    
                    // Run the query to start all the asynchronous processes.
                    List<IAsyncOperationWithProgress<SyndicationFeed, 
                        RetrievalProgress>> blogFeedOpsList = feedsQuery.ToList();
    
                    SyndicationFeed feed;
                    foreach (var blogFeedOp in blogFeedOpsList)
                    {
                        // The await operator retrieves the final result (a SyndicationFeed instance)
                        // from each IAsyncOperation instance.
                        feed = await blogFeedOp;
                        DisplayResults(feed);
                    }
                }
                catch (Exception ex)
                {
                    ResultsTextBox.Text =
                        "Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
                }
    
                // Reenable the button in case you want to run the operation again.
                StartButton.IsEnabled = true;
            }
    
            List<Uri> CreateUriList()
            {
                // Create a list of URIs.
                List<Uri> uriList = new List<Uri> 
                { 
                    new Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                };
                return uriList;
            }
    
    
            void DisplayResults(SyndicationFeed sf)
            {
                // Title of the blog.
                ResultsTextBox.Text += sf.Title.Text + "\r\n";
    
                // Titles and dates for blog posts.
                foreach (SyndicationItem item in sf.Items)
                {
                    ResultsTextBox.Text += "\t" + item.Title.Text + ", " +
                                        item.PublishedDate.ToString() + "\r\n";
                }
                ResultsTextBox.Text += "\r\n";
            }
        }
    }
    
  10. 選取 F5 鍵執行程式,然後選取 [開始] 按鈕。

建置完成的應用程式

您可以下載本主題中的範例。 Async 範例:從 .NET 的橋接至視窗 如果您想要設定您的應用程式,請遵循下列步驟。

  1. 啟動 Visual Studio 2012。

  2. 在功能表列上,選擇 [檔案]、[新增]、[專案]。

    [新增專案] 對話方塊隨即開啟。

  3. 在 [安裝] 中, [ [範本] 分類中,選取 [Visual Basic] 或 [Visual C#]],然後選取 [Windows 市集]。

  4. 從專案類型清單中,選取 [空白的應用程式 (XAML)]。

  5. 將專案命名為 WhenAnyBlogReader,然後選擇 [OK] 按鈕。

    新專案即會出現於 [方案總管] 中。

  6. 在 [方案總管] 中,開啟 MainPage.xaml 的捷徑功能表,然後選擇 [開啟]。

  7. 在 [XAML] 視窗中 MainPage.xaml,以下列程式碼取代程式碼。

    <Page
        x:Class="WhenAnyBlogReader.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AsTaskWhenAnyDemo"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Stretch" Margin="325,128,330,0" VerticalAlignment="Top" Click="StartButton_Click" Height="71" Background="#FFA89B9B" FontWeight="Bold" FontSize="36"/>
            <TextBox x:Name="ResultsTextBox" Margin="325,222,330,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" />
        </Grid>
    </Page>
    

    包含文字方塊和按鈕的簡易視窗會出現在 [設計] 視窗中 MainPage.xaml。

    如需可對應用程式各個改善和擴充的詳細資訊,請參閱 建立部落格讀取器

  8. 在 [方案總管] 中,開啟或 MainPage.xaml.vb MainPage.xaml.cs 的捷徑功能表,然後選擇 [檢視程式碼]。

  9. 使用下列程式碼取代或 MainPage.xaml.vb MainPage.xaml.cs 的程式碼。

    ' Add an Imports statement for SyndicationClient.
    Imports Windows.Web.Syndication
    
    ' Add an Imports statement for the Tasks.
    Imports System.Threading.Tasks
    
    ' The Blank Page item template is documented at http:'go.microsoft.com/fwlink/?LinkId=234238
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
        End Sub
    
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
    
            ResultsTextBox.Text = ""
    
            ' Disable the button until the operation is complete.
            StartButton.IsEnabled = False
    
            Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()
    
            ' Force the SyndicationClient to download the information.
            client.BypassCacheOnRetrieve = True
    
            Dim uriList = CreateUriList()
    
            ' The following code avoids the use of implicit typing so that you 
            ' can see the types clearly.
    
            Try
                Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
                    From uri In uriList
                    Select client.RetrieveFeedAsync(uri).AsTask()
                ' AsTask changes the returns from RetrieveFeedAsync into tasks.
    
                ' Run the query to start all the asynchronous processes.
                Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()
    
                Dim feed As SyndicationFeed
    
                ' Repeat the following until there are no tasks left:
                '    - Grab the first one that finishes.
                '    - Retrieve the results from the task (what the return statement 
                '      in RetrieveFeedAsync returns).
                '    - Remove the task from the list.
                '    - Display the results.
                While blogFeedTasksList.Count > 0
                    Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
                    feed = Await nextTask
                    blogFeedTasksList.Remove(nextTask)
                    DisplayResults(feed)
                End While
    
            Catch ex As Exception
                ResultsTextBox.Text =
                    "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
            End Try
    
            ' Reenable the button in case you want to run the operation again.
            StartButton.IsEnabled = True
        End Sub
    
    
        Function CreateUriList() As List(Of Uri)
    
            ' Create a list of URIs.
            Dim uriList = New List(Of Uri) From
            {
                    New Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
            }
            Return uriList
        End Function
    
    
        Sub DisplayResults(sf As SyndicationFeed)
    
            ' Title of the blog.
            ResultsTextBox.Text &= sf.Title.Text & vbCrLf
    
            ' Titles and dates for blog posts.
            For Each item As SyndicationItem In sf.Items
    
                ResultsTextBox.Text &= vbTab & item.Title.Text & ", " &
                                    item.PublishedDate.ToString() & vbCrLf
            Next
    
            ResultsTextBox.Text &= vbCrLf
        End Sub
    End Class
    
    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;
    
    // Add a using directive for SyndicationClient.
    using Windows.Web.Syndication;
    
    // Add a using directive for the Tasks.
    using System.Threading.Tasks;
    
    
    namespace WhenAnyBlogReader
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                ResultsTextBox.Text = "";
    
                // Disable the button until the operation is complete.
                StartButton.IsEnabled = false;
    
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
    
                // Force the SyndicationClient to download the information.
                client.BypassCacheOnRetrieve = true;
    
                var uriList = CreateUriList();
    
                // The following code avoids the use of implicit typing (var) so that you 
                // can identify the types clearly.
    
                try
                {
                    IEnumerable<Task<SyndicationFeed>> feedsQuery =
                            from uri in uriList
                            // AsTask changes the returns from RetrieveFeedAsync into tasks.
                            select client.RetrieveFeedAsync(uri).AsTask();
    
                    // Run the query to start all the asynchronous processes.
                    List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();
    
                    SyndicationFeed feed;
    
                    // Repeat the following until no tasks remain:
                    //    - Grab the first one that finishes.
                    //    - Retrieve the results from the task (what the return statement 
                    //      in RetrieveFeedAsync returns).
                    //    - Remove the task from the list.
                    //    - Display the results.
                    while (blogFeedTasksList.Count > 0)
                    {
                        Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
                        feed = await nextTask;                    
                        blogFeedTasksList.Remove(nextTask);
                        DisplayResults(feed);
                    }
                }
                catch (Exception ex)
                {
                    ResultsTextBox.Text =
                        "Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
                }
    
                // Reenable the button in case you want to run the operation again.
                StartButton.IsEnabled = true;
            }
    
    
            List<Uri> CreateUriList()
            {
                // Create a list of URIs.
                List<Uri> uriList = new List<Uri> 
                { 
                    new Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                };
                return uriList;
            }
    
    
            void DisplayResults(SyndicationFeed sf)
            {
                // Title of the blog.
                ResultsTextBox.Text += sf.Title.Text + "\r\n";
    
                // Titles and dates for blog posts.
                foreach (SyndicationItem item in sf.Items)
                {
                    ResultsTextBox.Text += "\t" + item.Title.Text + ", " +
                                        item.PublishedDate.ToString() + "\r\n";
                }
                ResultsTextBox.Text += "\r\n";
            }
        }
    }
    
  10. 選取 F5 鍵執行程式,然後選取 [開始] 按鈕。

請參閱

參考

WhenAny

AsTask

概念

使用 Async 和 Await 設計非同步程式 (C# 和 Visual Basic)

當其中一項工作完成時,取消剩餘的工作 (C# 和 Visual Basic)

啟動多項工作並在它們完成時進行處理 (C# 和 Visual Basic)

其他資源

快速入門:使用非同步程式設計的 Await 運算子

建立部落格讀取器

IAsyncOperationWithProgress