長い間ほったらかしにしていたWindowsストア向けのアプリ開発勉強再開しました。
環境: C++ VisualStudio2012forWindows8
まずは基礎から。と思ってhello world!やってみたけど、
XAML編集するだけで終わったので次のステップに。
1, 目標
画像を表示したい。
2, 仕様
仕様:
・XAMLにイメージビューを追加し、"ImageViewと"いう名前を設定する。
・ボタンが押されたときに呼び出されるイベントハンドラで、以下の処理を行う
1, イメージピッカーを表示し、ユーザーに画像を選択させる
2, ユーザーが選択したファイルの情報をもとに、画像ファイルを開く
3, 開いた画像ファイルを、ImageVewに表示する
3, ソースコード
ボタンが押されたときに呼び出されるイベントハンドラ中に以下のコードを記述する
create_task(openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
{
{
m_selected_file = file;
return m_selected_file->OpenAsync(FileAccessMode::ReadWrite);
}
}).then([this](IRandomAccessStream^ stream) // ラムダ式で自身のクラスメンバを参照するために、thisキャプチャを記述する
{
IRandomAccessStreamWithContentType^ imageData;
m_BmpImage = ref new BitmapImage();
m_BmpImage->SetSource(stream); // ここは同期処理なのでcreate_taskしなくてもよい。
ImageView->Source = m_BmpImage;
});
4, 作ってみた感想
WindowsアプリなんてMFC以来なもんで、色々と驚きアリ躓きあり。Asyncから始まる関数とかcreate_task関数とか。
躓いたポイントを以下に整理。
4.1, create_taskで記述した関数は、非同期に実行される。
レガシーなC/C++になれていると、この部分でまず詰まった。
create_task()で記述したブロックは非同期に実行される。
たとえば、ImageView->Sourceをcreate_taskのブロックチェーンの後ろに記述した場合、これは動作しない。
なぜなら、create_taskの実行結果を使うため。非同期に実行されるのでブロックチェーンの後ろではcreate_taskの実行完了は保障されない。
4.2, create_taskで記述したブロック内では、そのブロックスコープにある変数にしかアクセスできない
クラススコープやボタンクリックのイベントハンドラ内の関数スコープにある変数にアクセスできない。
引数としてもらってきたり、直前のcreate_taskの戻り値を受け取るなどの対処が必要。
とはいえ、GUIのコントロールに値を設定する場合などはクラススコープにアクセスできないと不便すぎる。
調べた結果、こういう記述ができるらしい。
create_task(openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
この行の[this]がポイント。
自分自身への参照が行えるようになる。(詳しいことはまだ理解できていない。)
4.3, 考察
マルチコア時代のプログラミングスタイルとして、こういった非同期プログラミングの需要はさらに増えていくと考えられる。これはどんどん勉強していかなければいけない領域だと思う。
こういう書き方は関数型プログラミングに通じるものを感じる。
関数型はまだ触り始めたばかりだけども。奥の深い言語だと思います。まる。