かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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される度に処理が実行されているのがわかると思います。