特集
» 2015年10月06日 05時00分 公開

特集:UWPとは何か:Windowsフォーム開発者のためのWindows 10 UWPアプリ開発入門(後編) (3/5)

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Platform Development]

4. 非同期! 非同期! 非同期!〜async/await

 UWPアプリでは非同期処理を多用する。「多用した方がよい」のではなく、非同期処理を使わざるを得ないのだ。というのも、ファイルアクセスやネットワークアクセスなど、処理に時間がかかるAPIがことごとく非同期処理になっているからである。非同期処理のコーディングは、Visual Studio 2012で導入されたasync/awaitキーワードによって簡潔に書ける。

 非同期処理は、Windowsフォームでももちろん記述できる。例として、Webページの内容を取得してそれをテキストボックスに表示するコードを、WindowsフォームとUWPアプリとで紹介しよう。

Windowsフォームでの非同期処理

 非同期処理の書き方にはさまざま方法があるが、ここではWebClientクラス(System.Net名前空間)を使った簡単な例を紹介する(別途公開のサンプルでは、「S3_Async」ディレクトリの下にある「S3_01_WinForm」プロジェクト)。ボタンのクリックイベントで非同期処理を開始し、非同期処理が終わったところでテキストボックスに結果を表示するというものだ(次のコード)。

private void button1_Click(object sender, EventArgs e)
{
  button1.Enabled = false;

  const string URL = "……省略……";
  System.Net.WebClient wc = new System.Net.WebClient();
  wc.Encoding = Encoding.UTF8;

  // 非同期処理が完了したときのイベントハンドラーをセットする
  wc.DownloadStringCompleted += DownloadCompleted;

  // 非同期処理を開始する
  wc.DownloadStringAsync(new Uri(URL));
}

// 非同期処理が完了したときのイベントハンドラー
private void DownloadCompleted(object sender,
                                DownloadStringCompletedEventArgs e)
{
  // 非同期処理が完了した後の処理
  textBox1.Text = e.Result;
  button1.Enabled = true;
}

WindowsフォームでWebページを非同期で取得するコードの例(コードビハインド、C#)
フォームには「button1」という名前のボタンと「textBox1」という名前のテキストボックスを配置しておく。
ボタンのクリックイベントハンドラーの中で、WebClientクラスのインスタンスを作り、そのDownloadStringAsyncメソッドを呼び出して、非同期処理を開始させる。ただし、非同期処理が完了したときのイベントハンドラーを事前に結び付けておく。非同期処理が完了すると、そのイベントハンドラーが呼び出されるので、そこで後続の処理を行う。
なお、このコードでは、Webページの文字エンコーディングがUTF-8であると想定している。

 上のコードでは、非同期処理を開始する記述と、非同期処理が完了した後に行う処理の記述が離れてしまっている。一般的に、従来の書き方ではこのような記述の分離が起きてしまい、コードの見通しが悪くなっていた。

UWPアプリでの非同期処理

 UWPアプリの場合は、非同期処理のAPIがasync/await対応になっているので、簡潔かつ分かりやすく書ける(次のコード、別途公開のサンプルでは「S3_Async」ディレクトリの下にある「S3_02_Uwp」プロジェクト)。UWPアプリでは、Webページの内容を取得するAPIとして、HttpClientクラス(System.Net.Http名前空間)が用意されている。

private async void button1_Click(object sender, RoutedEventArgs e)
{
  const string URL = "……省略……";

  button1.IsEnabled = false;

  var hc = new System.Net.Http.HttpClient();

  // 非同期処理を開始する
  string html = await hc.GetStringAsync(URL);

  // 非同期処理が完了した後の処理
  textBox1.Text = html;
  button1.IsEnabled = true;
}

UWPアプリでWebページを非同期で取得するコードの例(コードビハインド、C#)
フォームには「button1」という名前のボタンと「textBox1」という名前のテキストボックスを配置しておく。
先のWindowsフォーム用のコードと比べると、ボタンのクリックイベントハンドラーの中で記述が完結している。HttpClientクラスのインスタンスのGetStringAsyncメソッドを呼び出すことで非同期処理が始まるのだが、そこにawaitキーワードが付いている。これによって、非同期処理の開始と同時に、このメソッドからいったんリターンしてしまうのだ(asyncキーワードにより、リターンする型はvoidではなくTask型になる)。そして、非同期処理が完了した時点で割り込みが発生し、awaitキーワードを付加したメソッド呼び出し以降の処理が実行されるのである。
なお、GetStringAsyncメソッドでは、Webページの文字エンコーディングがUTF-8以外の場合に文字化けすることがある。文字エンコーディングを指定して読み取る方法は、「.NET TIPS: HttpClientクラスでシフトJISのWebページを取得するには?[C#、VB]」を参照してもらいたい。ただし、UWPアプリでは、EncodingクラスのGetEncodingメソッドを呼び出す前に、「Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);」という1行が必要だ(「WinRT/Metro TIPS: シフトJISのEncodingオブジェクトを取得するには?」を参照)。

 このように、async/awaitキーワードを使った書き方なら、非同期処理の開始と非同期処理完了後の処理を同じ場所に続けて記述できる。ただし、続いているのはコードの記述だけであって、実際の処理の流れは従来の非同期処理と同じだ。やはり非同期処理の学習は必要なのである。また、async/awaitキーワードを使った書き方は、Windowsフォームでも有効だ。UWPアプリを作らないとしても、async/awaitキーワードを使う新しい書き方に慣れておくのが得策だろう。

【コラム】 非同期処理についてさらに詳しく!

 タスクを使った新しい非同期処理については、次の記事をご覧いただきたい。

 MSDNでは、次のページを起点にするとよいだろう。

 非同期処理を一から学ぶための参考書も多く出ている。筆者も書籍を出しているので、参考にしていただければ幸いである。


Copyright© Digital Advantage Corp. All Rights Reserved.

編集部からのお知らせ

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。