クイック スタート: C# または Visual Basic での非同期 API の呼び出し

Applies to Windows and Windows Phone

Windows ランタイムには、時間がかかる可能性がある操作を実行しているときでも、アプリの応答性を保つために、さまざまな非同期 API が用意されています。 そのため、大量の操作が完了するのを待たずに、実行を継続できます。 たとえば、インターネットから情報をダウンロードするアプリは、情報が到着するまで数秒待機する可能性があります。同期メソッドを使って情報を取得すると、アプリはメソッドから制御が返されるまでブロックされます。アプリが操作に応答せず、応答していないと思ったユーザーが苛立ちを感じる可能性があります。 非同期 API を提供することによって、時間のかかる操作の実行時に、Windows ランタイムでアプリの応答性を保つことができます。

Windows ランタイムのほとんどの非同期 API には、対応する同期 API がありません。そのため、Windows ランタイム アプリで C# または Visual Basic を使って非同期 API を利用する方法を理解しておく必要があります。次に、Windows ランタイムの非同期 API を呼び出す方法を示します。

ロードマップ: このトピックと他のトピックとの関連については、以下をご覧ください。

必要条件

C# または Visual Basic を使った初めての Windows ランタイム アプリの作成」をご覧ください。

非同期 API の使用

非同期メソッドには、慣例により "Aync" で終わる名前が付いています。通常、非同期 API は、ユーザーがボタンをクリックしたときなど、ユーザーの操作に応じて呼び出します。 イベント ハンドラーでの非同期メソッドの呼び出しは、最も簡単な非同期 API の使用方法の 1 つです。 ここでは、例として await 演算子を使います。

たとえば、ブログ記事の特定の場所にあるタイトルを一覧表示するアプリがあるとします。 このアプリには、タイトルを取得する際にユーザーがクリックする Button があります。 タイトルは TextBlock に表示されます。 ユーザーがボタンをクリックし、ブログの Web サイトからの情報を待っている間、アプリの応答性を保つことが重要です。 この応答性を保つために、Windows ランタイムでは、フィードをダウンロードするための非同期メソッド SyndicationClient.RetrieveFeedAsync を提供しています。

この例では、非同期メソッド SyndicationClient.RetrieveFeedAsync を呼び出して、ブログから記事の一覧を取得します。これは、非同期メソッドを呼び出す最も簡単な方法です。


// Put the keyword, async on the declaration of the event handler.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{

    Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();

    // Force the SyndicationClient to download the information.
    client.BypassCacheOnRetrieve = true;

    Uri feedUri
        = new Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");

    try
    {
        // Call SyndicationClient RetrieveFeedAsync to download the list of blog posts.
        SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

        // The rest of this method executes after await RetrieveFeedAsync completes.
        rssOutput.Text = feed.Title.Text + Environment.NewLine;

        foreach (SyndicationItem item in feed.Items)
        {
            rssOutput.Text += item.Title.Text + ", " +
                             item.PublishedDate.ToString() + Environment.NewLine;
        }
    }
    catch (Exception ex)
    {
        // Log Error.
        rssOutput.Text =
            "I'm sorry, but I couldn't load the page," +
            " possibly due to network problems." +
            "Here's the error message I received: "
            + ex.ToString();
    }
}


この例には、いくつかの重要なポイントがあります。まず、SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) の行では、非同期メソッド RetrieveFeedAsync を呼び出す際に、await 演算子が使われています。await 演算子は、非同期メソッドを呼び出していることをコンパイラに伝えていると考えることができます。これにより、コンパイラが追加作業を行うようになります。もう 1 つは、イベント ハンドラーの宣言に async というキーワードが含まれているという点です。await 演算子を使うメソッドのメソッド宣言には、このキーワードを含める必要があります。async キーワードを要求した Button.Click イベント ハンドラーのシグネチャについては特に説明することはありません。async は、コンパイラがハンドラー本体からの非同期メソッドの呼び出しを許可できるように、意図的に追加されたものです。入力イベントの処理とそれらのイベント内の待機可能なメソッドの実行について詳しくは、「イベントとルーティング イベントの概要」をご覧ください。

このトピックでは、コンパイラでの await 演算子の処理方法については詳しく取り上げませんが、非同期で応答性を保つためにアプリが何を行っているか説明していきます。 同期コードを使った場合はどうなるか考えてみましょう。 たとえば、同期の SyndicationClient.RetrieveFeed というメソッドがあるとします (このようなメソッドは存在しませんが、ここではあると仮定します)。 アプリに SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) という行ではなく SyndicationFeed feed = client.RetrieveFeed(feedUri) という行が含まれている場合は、RetrieveFeed の戻り値が使用可能になるまで、アプリの実行は停止します。 アプリは、このメソッドが完了するのを待機している間、他のイベント (別の Click イベントなど) には応答できません。 つまり、RetrieveFeed が戻るまで、アプリはブロックされます。

しかし、client.RetrieveFeedAsync メソッドは、呼び出されると、取得を開始して直ちに戻ります。RetrieveFeedAsync と一緒に await を使うと、アプリが一時的にイベント ハンドラーを終了します。このとき、RetrieveFeedAsync を非同期で実行しながら、他のイベントを処理することができます。 これにより、アプリの応答性が維持されます。 RetrieveFeedAsync が完了し、SyndicationFeed が使用可能になると、アプリは、実質的に中断したイベント ハンドラーに戻り、SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) の後の残りのメソッドを完了します。

await 演算子を使うメリットは、架空の RetrieveFeed メソッドを使った場合のコードとそれほど違いがないという点です。 C# または Visual Basic で await 演算子を使わずに非同期コードを記述する方法もありますが、このようなコードでは、非同期で実行するしくみに重点が置かれる傾向があります。これにより、非同期コードが記述しづらく、わかりにくく、保守しにくいものになります。await 演算子を使うことによって、コードが複雑になることなく、非同期アプリのメリットを享受できます。

戻り値の型と非同期 API の結果

RetrieveFeedAsync へのリンクをたどると、RetrieveFeedAsync の戻り値の型が SyndicationFeed ではないことがわかると思います。 戻り値の型は、IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> になります。 未処理の構文の観点から見ると、非同期 API は、結果を含むオブジェクトを返します。 非同期メソッドが待機可能であると考えることは一般的であり、有用な場合もありますが、await 演算子は、実際にはメソッドではなくメソッドの戻り値を制御します。 await 演算子を適用すると、非同期メソッドの結果を取得することになります。 具体的には、未処理の構文で確認される、オブジェクトに対する GetResult の呼び出しの結果を取得します。この例では、SyndicationFeedRetrieveFeedAsync の結果です。

非同期メソッドを使う場合は、戻り値の型を確認することによって、結果に関する情報を取得することができます。 Windows ランタイムの各非同期 API は、次のいずれかの型を返します。

非同期メソッドの結果の型は、 TResult 型パラメーターと同じです。 TResult のない型には結果がありません。 その場合の結果は void と見なすことができます。 Visual Basic の Sub プロシージャは、戻り値の型が void のメソッドと同じです。

次の表に、非同期メソッドの例と、それぞれの戻り値と結果の型を示します。

非同期メソッド戻り値の型結果の型
SyndicationClient.RetrieveFeedAsync IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> SyndicationFeed
FileOpenPicker.PickSingleFileAsync IAsyncOperation<StorageFile> StorageFile
XmlDocument.SaveToFileAsync IAsyncAction void
InkStrokeContainer.LoadAsync IAsyncActionWithProgress<UInt64> void
DataReader.LoadAsync DataReaderLoadOperationIAsyncOperation<UInt32> を実装するカスタムの結果クラス UInt32

 

.NET for Windows Runtime apps で定義されている非同期メソッドの戻り値の型は Task または Task<TResult> です。 Task を返すメソッドは、IAsyncAction を返す Windows ランタイム非同期メソッドに似ています。 どちらの場合も、非同期メソッドの結果は void です。 戻り値の型 Task<TResult> は、 タスク実行時の非同期メソッドの結果が TResult 型パラメーターと同じ型であるという点で、IAsyncOperation<TResult> に似ています。 .NET for Windows Runtime apps とタスクの使い方について詳しくは、「Windows ランタイム アプリ用 .NET の概要」をご覧ください。

エラーの処理

await 演算子を使って非同期メソッドから結果を取得する場合は、同期メソッドの場合と同じように、try/catch ブロックを使って非同期メソッドで発生するエラーを処理できます。 前の例では、RetrieveFeedAsync メソッドと await 操作が try/catch ブロックでラップされて、例外がスローされたときにエラーを処理するようになっています。

非同期メソッドが他の非同期メソッドを呼び出している場合は、例外が発生した非同期メソッドが外側のメソッドに伝達されます。 つまり、最も外側のメソッドで try/catch ブロックを使うと、入れ子になった非同期メソッドのエラーをキャッチできます。これも、同期メソッドで例外をキャッチする方法と同様です。ただし、catch ブロックで await を使うことはできません。

要約と次のステップ

ここで説明した非同期メソッドの呼び出しのパターンは、イベント ハンドラーで非同期 API を呼び出す場合に使う最も簡単な方法です。 このパターンは、void または Sub (Visual Basic) を返すオーバーライドされたメソッドで非同期メソッドを呼び出す場合にも使うことができます。

Windows ランタイムで非同期メソッドを使う場合は、次の点を忘れないでください。

  • 非同期メソッドには、慣例により "Aync" で終わる名前が付いています。
  • await 演算子を使うメソッドには、async キーワードでマークされた宣言が必要です。
  • アプリは、await 演算子を見つけると、非同期メソッドの実行中もユーザー操作への応答性を保ちます。
  • 非同期メソッドは、結果を含むオブジェクトを返します。 一般的には、戻り値から得られる結果は有用な何かであり、戻り値そのものではありません。 結果の型は、戻り値の型を見ればわかります。
  • 非同期 API と async パターンを使うことにより、アプリのパフォーマンスが向上する場合があります。非同期 API を使った場合のパフォーマンス上のメリットについて詳しくは、「UI スレッドの応答性の確保」をご覧ください。このトピックでは、非同期となるようにロジックを Task として実装する方法について説明しています。

このトピックの例では、次のようなテキストが出力されます。

Windows Experience Blog
PC Snapshot: Sony VAIO Y, 8/9/2011 10:26:56 AM -07:00
Tech Tuesday Live Twitter #Chat: Too Much Tech #win7tech, 8/8/2011 12:48:26 PM -07:00
Windows 7 themes: what’s new and what’s popular!, 8/4/2011 11:56:28 AM -07:00
PC Snapshot: Toshiba Satellite A665 3D, 8/2/2011 8:59:15 AM -07:00
Time for new school supplies? Find back-to-school deals on Windows 7 PCs and Office 2010, 8/1/2011 2:14:40 PM -07:00
Best PCs for blogging (or working) on the go, 8/1/2011 10:08:14 AM -07:00
Tech Tuesday – Blogging Tips and Tricks–#win7tech, 8/1/2011 9:35:54 AM -07:00
PC Snapshot: Lenovo IdeaPad U460, 7/29/2011 9:23:05 AM -07:00
GIVEAWAY: Survive BlogHer with a Sony VAIO SA and a Samsung Focus, 7/28/2011 7:27:14 AM -07:00
3 Ways to Stay Cool This Summer, 7/26/2011 4:58:23 PM -07:00
Getting RAW support in Photo Gallery & Windows 7 (…and a contest!), 7/26/2011 10:40:51 AM -07:00
Tech Tuesdays Live Twitter Chats: Photography Tips, Tricks and Essentials, 7/25/2011 12:33:06 PM -07:00
3 Tips to Go Green With Your PC, 7/22/2011 9:19:43 AM -07:00
How to: Buy a Green PC, 7/22/2011 9:13:22 AM -07:00
Windows 7 themes: the distinctive artwork of Cheng Ling, 7/20/2011 9:53:07 AM -07:00

関連トピック

C# または Visual Basic を使った Windows ランタイム アプリのためのロードマップ
タスク ベースの非同期パターン (TAP) に関するホワイトペーパー
リバーシの機能のシナリオ: 非同期コード

 

 

表示:
© 2014 Microsoft