かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Reactive Extensions入門 12「非同期実行のためのメソッド」

なんだかんだで、このシリーズも12回目になりました。
説明順番は、見知ったもの、面白そうなものという順番なので特に意味はありませんが、今日は、Observableに定義されているメソッドの中から、非同期実行をIObservableにしてくれる人たちから一部分だけ紹介したいと思います。

Startメソッド

引数で渡したデリゲートを非同期実行してくれます。このメソッドの戻り値のIObservableは、実行結果をキャッシュしてるみたいでSubscribeすれば、そのつど実行結果を返してくれます。

ToAsyncメソッド

68個という凄まじい数のオーバーロードがあるメソッドで、デリゲートを渡すと、そいつを非同期実行してIObservableを返すデリゲートを返してくれます。
また、ActionやFuncの拡張メソッドとして定義されているため、func.ToAsync()のように呼ぶことも出来ます。(後で紹介するサンプルプログラムではstaticメソッドの形で呼び出してます)

Deferメソッド

引数で渡されたIObservableを返すデリゲートを、Subscribeする度に実行してくれるIObservableを返すメソッドです。

プログラム例

自分で説明してて何がなんだかわからなくなってきたので、サンプルのプログラムを書いてみます。

// 引数で渡されたデリゲートを非同期実行してくれる
var ob = Observable.Start(() => 
    {
        Console.WriteLine("Observable.Start!!");
        return "Hello Start";
    });
// 結果を受けとる
ob.Subscribe(Console.WriteLine);
ob.Subscribe(Console.WriteLine);

Console.ReadKey();

// 引数で渡されたデリゲートを非同期実行するデリゲートを返す
var ob2 = Observable.ToAsync(() =>
    {
        Console.WriteLine("Observable.ToAsync!!");
        return "Hello ToAsync";
    })(); // ()で呼び出すことでStartと同じような動きになる
// 結果を受け取る
ob2.Subscribe(Console.WriteLine);
ob2.Subscribe(Console.WriteLine);
            
Console.ReadKey();

// 引数で渡されたIObservable<T>を返すデリゲートを非同期で
// 実行してくれるような動きをするけど・・・
var ob3 = Observable.Defer(Observable.ToAsync(() =>
    {
        Console.WriteLine("Observable.Defer!!");
        return "Hello Defer";
    }));
// Subscribeする度に処理が実行される。
ob3.Subscribe(Console.WriteLine);
ob3.Subscribe(Console.WriteLine);
Console.ReadKey();

実行すると、以下のような結果になります。

Observable.Start!!
Hello Start
Hello Start
Observable.ToAsync!!
Hello ToAsync
Hello ToAsync
Observable.Defer!!
Hello Defer
Observable.Defer!!
Hello Defer

注目すべきところはDeferの実行結果です。Subscribeされる度に処理が実行されているのがわかると思います。