タスクを使って非同期プログラミングを簡単に。おお、これは分かりやすく非同期周りについて網羅されてる!あと、私はTask全然知らないので初歩から入る導入はお役立ちです。いやまあ、実際のとこTask周りの導入記事っていっぱいあるのに、未だにお役立ち、とか言ってるのもどうかと思わなくもないところではあるんですが不勉強なもので。Model)、そしてTask。Extensionsが欠けています。いうわけで、Taskと対比させながらRxでのコードを見ていきましょう。非同期実行、そして待機MSDNマガジンでは真ん中辺りからのタスクのコードを、Rxでのコードと一緒に並べてみます。余談:タスクはIObservableに変換出来たりするtask.ToObservable().Run(Console.WriteLine);どちらもデフォルトではThreadPoolで非同期を実行します。ThreadPoolと違うのは、待機するのも戻り値を取り出すのも簡単。Rxでは長さ1のReactiveシーケンスとして扱われるので、Firstを使うと同期的にブロックして値を取り出せます。task.ResultなTaskより扱いやすいのではないかと思います。両者ともに似ているので、TaskからIObservable<T>への変換も容易です。System.Reactive.dllを読みこめば、Taskに対してToObservableメソッドが追加され、簡単に変換することが出来ます。汎用的に非同期処理をTaskに、Rxに変換しよう。TaskにはTaskCompletionSourceが、RxにはAsyncSubjectがあります。r);こちらもまた、両者ともに実によく似ています。何らかの任意の非同期処理は、使いやすいようにRxに包んでしまうと素敵な気分になれる。IAsyncResultパターンの変換IAsyncResultパターン。Model、略してAPMと呼ぶそうです。Richterはリッチャーと呼ぶべきかリヒターと呼ぶべきなのか謎という話ががが。一冊は未定というか将来のために取っておくというか)だと思うので未読の人は是非是非。思ったら絶版じゃないですか!いや、amazonで偶然品切れなだけかもしれませんが、どうなんでしょう。Editionが出ています。!今読み返したら20ページほど費やされて色々書いてありました。ぶっちゃけ面倒くさいと思って半分以上流し読みしてたという事実に気づいてしまったり。Editionの時に拾い直せば......。そんなわけで、その面倒くささを緩和するFromAsync/FromAsyncPatternをどうぞ。残念なことに、Taskには組み込みの変換パターンがないので、TaskCompletionSourceを使って自前で作る必要があるようです。RxではAsyncSubjectを使って自前で用意するまでもなく、そもそもイベントのLinq化として売り出されたので、イベントベースのパターンの変換はお手の物です。同期で待機&受け取りConsole.WriteLine(result);FromEvent。実に美しい!Linq!Linq!おっと、興奮してしまった。いえ、stringでイベント名を指定するのも、h=>hoge+=の連打も、どちらも悲しくダサい。TemplateでFromEventに包んだのを一気に自動生成してしまうのをお薦めします。頑張ったし便利だと思ったけれど、はてブ数がああああ。そんなわけで、Rxをガリガリ使う分には必需品です。それで大丈夫か?FromEventの後者の書き方は問題を残しています。DownloadStringAsyncの後にFirst。危険かというと......。e.EventArgs.Result).First();Firstだと同期で延々と待つのでフリーズ。Subscribeならフリーズはありませんが、結果がこないので意図した結果ではないでしょう。そんな時はTake-Prune-Connectパターン、なんてものはなく今思いつきました。今思いついたのでこれがベストなやり方なのか、ちょっとよく分からないのであとでForumとか見て調べておきます。挙動的には全然問題ない。何度でも取り出せるConsole.WriteLine(result2);わけわかんなくなってきました?失望のため息が聞こえます。したものかねえ、これ。PruneはキャッシュとしてAsyncSubjectを持って後続に渡します。値を流すタイミングを自由に調整出来ます(Connectしたら流す、それまでは値が来ていても堰止める)。今回はFromAsyncPatternをなぞらえるため、即座にConnectしました。やっていることは、上の方で出したAsyncSubjectのパターンのシミュレーションです。OnNextが一回来て、OnCompletedが来る。ないと、AsyncSubjectが完了しない。FromEventはそのままだと無限リスト状態で完了の状態がこないので、Take(1)で長さ1のReactiveシーケンスとする。することで、後ろに非同期結果の値が流れ出します。一つの非同期実行程度なら、APMだろうがイベントモデルだろうが、素のまま扱っても別にそこまで面倒なわけではない。Taskが、Rxが真価を発揮するのは複数の操作を行うとき。複数を同時に走らせて待機がいとも簡単に。Rxは非同期特化というわけではないので直接的にアレとコレのどっちかが来るまで待ってね、なんていうメソッドはないのですが、豊富な結合系メソッドで余裕でシミュレート出来てしまいます。WaitAnyはMerge.Takeで。WaitAllはConcatで。