Share via


WhenAny: .NET Framework と Windows ランタイム間のブリッジ (C# および Visual Basic)

このトピックの例は、タスクが完了した順に実行される非同期のタスクを処理する .NET Framework メソッドと非同期にブログ フィードをダウンロードする Windows ランタイム 型を結合します。 この型の詳細については、「SyndicationClient」を参照してください。 メソッドの詳細については、「Task.WhenAny」を参照してください。

これらの機能を結合すると、同時に複数のブログ フィードのダウンロードを開始し、ダウンロードの完了と同時に結果を処理できます。 1 つのフィードが他よりも速くダウンロードされた場合、その結果が先頭に表示されます。 SyndicationClient メソッドを使用すると、フィードを簡単にダウンロードできます。Task.WhenAny メソッドを使用すると、ダウンロードが完了した次のフィードをさらに簡単に識別できます。

注意

例を実行するには、Windows 8 がコンピューターにインストールされている必要があります。また、Visual Studio から例を実行するには、Visual Studio 2012、Visual Studio 2013、Visual Studio Express 2012 for Windows 8、または Visual Studio Express 2013 for Windows もインストールされている必要があります。

次のコードは 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

このトピックの残りの部分では、例の作成とその動作についての詳細を提供します。

例を実行するには、Visual Studio 2012 および Windows 8 がコンピューターにインストールされている必要があります。

このトピックは、次のセクションで構成されています。

  • 例のセットアップ オプション
  • スタート コードについて
  • スタート コードを拡張する
  • スタート コードをダウンロードする
  • 完成したアプリケーションをダウンロードする
  • スタート コードをビルドする
  • 完成したアプリケーションをビルドする
  • 関連トピック

例のセットアップ オプション

例は、「クイック スタート: await 演算子を使用した非同期プログラミング」に説明されているブログ リーダーに基づいています。 ただ、このトピックのスタート コードは、1 つではなく複数のブログ フィードをダウンロードします。

スタート コードは、ブログ フィードを順番にダウンロードするために Windows ランタイム の機能を使用します。 つまり、ブログ フィードは URL のコレクション内の一覧にある順序でダウンロードされます。 完成したアプリは、ブログ フィードを完了した順にダウンロードする機能を .NET Framework から追加します。

この例のコードは、次のいずれかの方法で設定できます:

  • スタート コード。

  • 完了したアプリ。

    • 完了したアプリをダウンロードするの手順に従って完了したアプリをダウンロードできます。

    • 完了したアプリをビルドするの手順に従って完了したアプリをビルドできます。

    • 完了したアプリをビルドするにスクロールすると、完了したアプリを実装せずに確認できます。

スタート コードについてのセクションでは、基本的なソリューションのキー ポイントを説明します。

スタート コードを拡張するのセクションでは、AsTask``2Task.WhenAny を追加して、コードを変更する方法を示します。

スタート コードについて

スタート コードは、URL の一覧内の各 URL からブログ フィードをダウンロードするために SyndicationClient メソッドの、RetrieveFeedAsync を使用します。 このメソッドの各呼び出しは、進行中の非同期操作を表す IAsyncOperationWithProgress インスタンスを戻します。 待機状態になると、非同期操作は、ダウンロードされたブログ フィードに関する情報を含む SyndicationFeed インスタンスを生成します。

コードは URI の一覧の各エントリに RetrieveFeedAsync を適用するクエリを定義します。 実行すると、クエリは 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``1 は、次のコードに示すように、クエリを実行して非同期プロセスを開始します。

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

この時点で、アクティブな IAsyncOperationWithProgress インスタンスの一覧があります。 各インスタンスが最終的な結果を得るまで、さらに待機する必要があります。

次のループは SyndicationFeed の結果を取得するために、IAsyncOperationWithProgress の各インスタンスを待機させます。

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

トピックの最後のスタート コードをビルドするのセクションで、プログラムのこのバージョンを確認できます。

非同期の Windows ランタイム API のプログラミングに関する詳細については、「クイック スタート: await 演算子を使用した非同期プログラミング」を参照してください。

スタート コードを拡張する

スタート コードは SyndicationClient がブログ フィードのダウンロードを簡単にすることを示します。 この例を完了する残りの手順によって、アプリケーションが、URI の一覧に表示される順序の代わりに、ダウンロードが完了した順にブログ フィールドを処理できるようにします。

拡張を達成するキーは、Task.WhenAny メソッドです。 非同期プロセスのコレクションに WhenAny を適用すると、待機時間を短縮するために、メソッドは最初に完了したプロセスを戻します。 この例では、ブログ フィードの情報を表示する順序は重要ではありません。 1 つのダウンロードが遅い場合、別のブログの結果が先に表示されます。 この状態は、次の 1 点を除き、適切な WhenAny です: WhenAny はタスクのコレクションを要求します。

AsTask の呼び出し

WhenAny は Task または Task のインスタンスのコレクションを必要としますが、ブログ フィードをダウンロードする SyndicationClient メソッドは、IAsyncOperationWithProgress インスタンスを戻します。 このため、アプリケーションは Windows ランタイム の IAsyncOperationWithProgress オブジェクトと .NET Framework の Task のオブジェクトの間をブリッジする必要があります。

.NET Framework は遷移を実行する AsTask``2 拡張メソッドを提供します。 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 は、広く認識されていませんが、非同期プログラミングの重要なロールを果たします。次のコードに示すように、IAsyncAction または IAsyncOperation のインスタンスに await 演算子を適用するたびに、コンパイラは AsTask を使用します。

WhenAny を適用する

変換の最後の手順では、アプリに Task.WhenAny メソッドを追加することです。 WhenAny は、タスク (blogFeedTasksList) のコレクションに適用され、コレクションで最初に完了したタスクを戻します。 つまり、WhenAny は、待機中の場合、最初に終了したタスクを評価するタスクを戻します。

次のステートメントは、WhenAny を呼び出すか、結果を待機します。 コードは明示的な型指定を使用して結果をより明確に示します。

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

次のコードは前のステートメントと同じ動作を実行しますが、何が起きているかを明確にするために、2 つのステートメントに操作を分割しています。 最初のステートメントは WhenAny を呼び出し、2 番目のステートメントはその結果を待機します。

' 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;

最後に、最初に終了したタスクから結果 (SyndicationFeed インスタンス) を取得するために nextTask を待機する必要があります。その後、再度プロセスしないように一覧から nextTask からタスクを削除します。

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

blogFeedTasksList の各タスクに対してこれらの手順を実行するには、while ループを使用します。

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 の使用は、例に示すように、いくつかのタスクを格納する問題の場合、問題なく使用できます。ただし、多数のタスクが処理する場合、他のアプローチがより効率的です。詳細と例については、「Processing tasks as they complete (完了したタスクを処理する)」を参照してください。

スタート コードをダウンロードする

この例のスタート コードは、「Async Sample: Bridging from .NET to Windows (非同期のサンプル: .NET から Windows へのブリッジ)」からダウンロードできます。 インターネットにアクセスできない場合、このトピックの最後にあるスタート コードをビルドするの指示に従って、スタート コードを作成します。

コードをダウンロードした後、これを開いて実行するには、次の手順に従います。

  1. ダウンロードしたファイルを圧縮解除し、Visual Studio 2012 を開始します。

  2. メニュー バーで [ファイル][開く][プロジェクト/ソリューション] の順に選択します。

  3. 圧縮解除したサンプル コードが含まれるフォルダーに移動し、AsTaskWhenAnyDemoVB または AsTaskWhenAnyDemoCS のソリューション (.sln) ファイルを開きます。

  4. ソリューション エクスプローラーで、SequentialBlogReader プロジェクトのショートカット メニューを開き、[スタートアップ プロジェクトに設定] をクリックします。

  5. F5 キーを押してプロジェクトをビルドし、実行します。

  6. 結果が常に同じ順序で表示されることを確認するために、コードを複数回実行します。

トピックの最後のスタート コードをビルドするのセクションにある MainPage.xaml.vb または MainPage.xaml.cs ファイルを確認できます。

例は、「クイック スタート: await 演算子を使用した非同期プログラミング」に説明されているブログ リーダーに基づいています。 ただ、このトピックのスタート コードは、1 つではなく複数のブログ フィードをダウンロードします。

アプリケーションに実行できる、多数の改善と拡張の詳細については、「ブログ リーダーを作成する」を参照してください。

完成したアプリケーションをダウンロードする

例のビルドを実行せずに、例全体をダウンロードすることも可能です。 スタート コードをダウンロードするのセクションの指示に従います。ただし、スタートアップ プロジェクトとして WhenAnyBlogReader を選択します。

ブログ フィードが異なる順序で表示されることを確認するため、プログラムを複数回実行します。

トピックの最後の完成したアプリをビルドするのセクションにある MainPage.xaml.vb または MainPage.xaml.cs ファイルを確認できます。

スタート コードをビルドする

このトピックの例は、「Async Sample: Bridging from .NET to Windows (非同期のサンプル: .NET から Windows へのブリッジ)」からダウンロードできます。 アプリケーションの設定を自分で行いたい場合は、次の手順に従います。

  1. Visual Studio 2012 を起動します。

  2. メニュー バーで [ファイル][新規][プロジェクト] の順にクリックします。

    [新しいプロジェクト] ダイアログ ボックスが表示されます。

  3. [インストール済み][テンプレート][Visual Basic] または [Visual C#] の順にクリックし、プロジェクトの種類の一覧の [Windows ストア] をクリックします。

  4. プロジェクトの種類の一覧の [新しいアプリケーション (XAML)] をクリックします。

  5. プロジェクトに「SequentialBlogReader」という名前を付け、[OK] をクリックします。

    ソリューション エクスプローラーに新しいプロジェクトが表示されます。

  6. [ソリューション エクスプローラー]で、MainPage.xaml のショートカット メニューを開き、[開く] をクリックします。

  7. MainPage.xaml の [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 キーを押してプログラムを実行し、[Start] を複数回クリックします。

完成したアプリケーションをビルドする

このトピックの例は、「Async Sample: Bridging from .NET to Windows (非同期のサンプル: .NET から Windows へのブリッジ)」からダウンロードできます。 アプリケーションの設定を自分で行いたい場合は、次の手順に従います。

  1. Visual Studio 2012 を起動します。

  2. メニュー バーで [ファイル][新規][プロジェクト] の順にクリックします。

    [新しいプロジェクト] ダイアログ ボックスが表示されます。

  3. [インストール済み][テンプレート] カテゴリ、[Visual Basic] または [Visual C#][Windows ストア] の順に選択します。

  4. プロジェクトの種類の一覧から [新しいアプリケーション (XAML)] をクリックします。

  5. プロジェクトに「WhenAnyBlogReader」という名前を付け、[OK] をクリックします。

    ソリューション エクスプローラーに新しいプロジェクトが表示されます。

  6. [ソリューション エクスプローラー]で、MainPage.xaml のショートカット メニューを開き、[開く] をクリックします。

  7. MainPage.xaml の [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 キーを押してプログラムを実行し、[Start] を複数回クリックします。

参照

関連項目

WhenAny``1

AsTask``1

概念

Async および Await を使用した非同期プログラミング (C# および Visual Basic)

完了後の残りの非同期タスクのキャンセル (C# および Visual Basic)

完了時での複数の同期タスクとプロセスの実行 (C# および Visual Basic)

その他の技術情報

クイック スタート: await 演算子を使用した非同期プログラミング

ブログ リーダーを作成する

IAsyncOperationWithProgress