Kikuchy's Second Memory

つくる楽しさをもっと伝えたい。プログラムを書いていて、わからなかったこと・気付いた事を書き留めています。

Windows ランタイム コンポーネント でasyncなメソッドを公開する

本題の前に宣伝させてください。

Windows ストア アプリ 開発の会第2回の開催が決まりました!!

学生の方限定ですが、無料で参加していただけます。
当日はMSPフェローの三村さんと私と、参加者の皆様で、テンプレートベースのWindowsストアアプリを開発し、ストアへの登録を行うことを目標としています。
「あまりコーディングできないよ!」というデザイナーなどの方のために、ほとんどコーディングを行わなくてもアプリを作れるテンプレートを用意していますのでご安心ください。むしろ、そういう方にも参加していただいて、Windowsストアアプリのデザインをしていただきたいと思います。

↓あなたの参加をお待ちしております!
Windows 8発売記念! Microsoft Student Partners 主催 Windows ストア アプリ 開発の会 in 東京 #2 : ATND



ここから本題です。
「Windows ランタイム コンポーネント」って作ったことありますか?
あれです、「ストアアプリならどの言語からも使えちゃうライブラリ」って奴です。
このスライドの8ページに記載されているWindowsメタデータのことです。

要は、
この形式でライブラリを作れば、C#からでもVBからでもC++/CXからでもHTML+JavaScriptからでも使える
ってことです。ストアアプリの開発に限定されますが!

詳しい解説と開発のはじめ方についてはこちらのページをお読みください。


さて、このランタイムコンポーネントですが、開発についていくつかの制限がついて回ります。
その中でも、C#VBで開発しているときに、Taskクラスを返すメソッドを公開できないというものがあります。
え、どういうこと?
要するに、

// ライブラリ使う方
var myLib = new MyLibrary();
await myLib.SomeProcedureAsync();
string str = await myLib.GetHogeAsync();

こうやって使えるライブラリを作りたいのに、

// ライブラリの中
public async Task SomeProcedureAsync()
{
    ......
}

public async Task<string> GetHogeAsync()
{
    ......
}

こうしたメソッドが作れない、ということです。




なんてこった!
ネットワークやファイルのIOを行うライブラリでawaitできないのは致命的ですね!

ですが、こうすれば解決。

// ライブラリの中
// ↓元"SomeProcedureAsync()。名前とアクセスレベルを変えた"
internal async Task SomeProcedureInnerAsync()
{
    ......
}

// ↓元"GetHogeAsync()"
internal async Task<string> GetHogeInnerAsync()
{
    ......
}

public IAsyncAction SomeProcedureAsync()
{
    return this.SomeProcedureInnerAsync().AsAsyncAction();
}

public IAsyncOperation<string> GetHogeAsync()
{
    return this.GetHogeInnerAsync().AsAsyncOperation();
}

これだけでコンパイルが通りますし、思い通りにawaitできるメソッドになります。

本当はこのままだと「Asyncメソッドの処理を途中でキャンセルできない」とかがあるのですけれど。詳しいことは参考ページをお読みください。



参考