Download - 実践 Reactive Extensions
![Page 1: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/1.jpg)
実践 Reactive Extensions
2011/08/27 Silverlight/Phone Quest I
伊勢 シン
(Microsoft MVP for Windows Phone)
![Page 2: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/2.jpg)
自己紹介 • 伊勢 シン
– Microsoft MVP for Windows Phone (Oct 2010-Sep 2011)
• 大阪で働くスマートフォンプログラマ – 目指すは「スマートフォンの万屋」 – iOSアプリをビルドをしながらAndroidアプリのコーディングやったりとか
– Windows Phone 7 も少々
• 趣味もスマートフォンアプリ開発で – EbIRC
– SongTweeter
• コミュニティ – スマートフォン勉強会 代表
– Windows Phone Arch 関西スタッフ?
![Page 3: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/3.jpg)
おしながき
• Reactive Extension について
–基本的なこと
–書き方の考え方
• 実例でみるReactive Extensions
– RSSの取得
– ログインが必要なページの先からファイルダウンロード
–複数ページをダウンロードして一括処理
–なんでもいいからとにかく非同期
![Page 4: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/4.jpg)
Reactive Extensions について
![Page 5: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/5.jpg)
そもそもReactive Extensionsって何ぞ
• Reactive Extensions (Rx)
• LINQの機能を時間軸に拡張するライブラリ
– LINQ to SQL, LINQ to Objects に対する
LINQ to Events, LINQ to Asynchronous
– “WhereでフィルタしてSelectで射影できるならLINQ
といえる” – by @neuecc
![Page 6: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/6.jpg)
なにがうれしいの? • 複雑な非同期処理を「直線的に」書ける
– 非同期のコードはひたすらネストがつづく – “もはやカオスすぎて頭が痛い” by @neuecc
• 例外処理をひとまとめに書ける – Subscribeの第2引数のラムダで一括処理可能
• その他各種特典 – 中断処理も簡単。
– リトライ処理
– 処理の待ち合わせ、結合など
![Page 7: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/7.jpg)
“もはやカオスすぎて頭が痛い” 例
![Page 8: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/8.jpg)
そう、Rxならね
WebRequest.Create("http://hoge") .GetResponseAsObservable() .Select(res => new StreamReader(res.GetResponseStream()).ReadToEnd()) .SelectMany(s => WebRequest.Create(s).GetResponseAsObservable()) .Select(res => new StreamReader(res.GetResponseStream()).ReadToEnd()) .ObserveOnDispatcher() .Subscribe( s => MessageBox.Show(s), e => MessageBox.Show(e.ToString()));
![Page 9: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/9.jpg)
どこでつかえるの?
• Windows Phone のクラスライブラリに 標準搭載され、非同期処理しか存在しない Silverlight の存在も相まって注目度アップ
• WP7だけでなく、いろいろなところでつかえます
– .NET Framework 3.5 / 4 Client Profile
– Silverlight 3 / 4 / for Windows Phone
– XNA 3.1(Zune) / 4 (Xbox360)
– http://www.microsoft.com/download/en/details.aspx?id=24940
![Page 10: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/10.jpg)
どうやって使うの?@WP7
• 以下のアセンブリを参照
– Microsoft.Phone.Reactive
– System.Observable
• Rxを使いたいcsファイルのusingに以下を追加
– Microsoft.Phone.Reactive
• すべてのはじまりは Observable クラス
![Page 11: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/11.jpg)
そもそもマルチスレッドの基本的な考え方
UIスレッド
トリガー
時間のかかる処理
どこか別のスレッド
結果の処理
スレッド同期
UI反映
![Page 12: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/12.jpg)
Rx コードの基本構成
Observable.FromAsyncPattern<WebResponse>( req.BeginGetResponse, req.EndGetResponse)() .Select(res => XDocument.Load(res.GetResponseStream())) .SelectMany(doc => doc.Element("Categories").Elements("Category")) .Select(elem => new { ID = elem.Element("ID").Value, Name = elem.Element("Name").Value }) .ObserveOnDispatcher() .Subscribe(res => { // UI反映 }, err => { // 例外処理 });
1.トリガー
2.データ処理
3.スレッド同期
4.UI反映
![Page 13: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/13.jpg)
簡単にRxを書くために
• 通信処理系のRxを書くなら
RxAsynchronousHelper を使うと便利です。
–通信を非同期に行うためのRxのおきまり処理を
うまくパッケージングしたクラス。あるだけで便利。
– by @neuecc
– http://neue.cc/2010/11/26_286.html
![Page 14: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/14.jpg)
実例で見る
Reactive Extensionsの使い方
![Page 15: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/15.jpg)
RSSを受信する
• 単純な処理の例
– XDocumentの名前空間つけないといけないのだけなんとかならんかと思っています。
![Page 16: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/16.jpg)
単純なRSS受信
var req = WebRequest.CreateHttp("http://d.hatena.ne.jp/iseebi/rss"); Observable.FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse)() .Select(res => XDocument.Load(res.GetResponseStream())) .Select(doc => from elem in doc.Element(Name_RDF).Elements(Name_Item) select new { Title = elem.Element(Name_Title).Value, Link = elem.Element(Name_Link).Value }) .ObserveOnDispatcher() .Subscribe(res => { foreach (var item in res) { Debug.WriteLine("{0} -> {1}", item.Title, item.Link); } });
private const string Name_RDF = "{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF"; private const string Name_Item = "{http://purl.org/rss/1.0/}item"; private const string Name_Title = "{http://purl.org/rss/1.0/}title"; private const string Name_Link = "{http://purl.org/rss/1.0/}link";
![Page 17: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/17.jpg)
RxAsynchronousHelperを使った場合
WebRequest.CreateHttp("http://d.hatena.ne.jp/iseebi/rss") .GetResponseAsObservable() .Select(res => XDocument.Load(res.GetResponseStream())) .Select(doc => from elem in doc.Element(Name_RDF).Elements(Name_Item) select new { Title = elem.Element(Name_Title).Value, Link = elem.Element(Name_Link).Value }) .ObserveOnDispatcher() .Subscribe(res => { foreach (var item in res) { Debug.WriteLine("{0} -> {1}", item.Title, item.Link); } });
![Page 18: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/18.jpg)
ダウンロードの結果解析で次のファイルへ
• ログインが必要なページなどに有効
• SelectManyにすれば、流れに全く関係のないIObservable<T> を新規にメソッドチェーンに
流せる。
![Page 19: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/19.jpg)
テキストに書いてあるURLをさらに取得
// URLが書いてある WebRequest.CreateHttp("http://iseebi.half-done.net/test/url.txt") .DownloadStringAsync() // 新しいIObservableを流す .SelectMany(res => WebRequest.CreateHttp(res).DownloadStringAsync()) .ObserveOnDispatcher() .Subscribe(res => { Debug.WriteLine(res); });
![Page 20: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/20.jpg)
一括ダウンロードしてから処理
• 複数のファイルをダウンロードし、
ダウンロード完了後に処理したい場合
–定義ファイルの一括取得など
![Page 21: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/21.jpg)
一括ダウンロード
// ダウンロード処理を一括でリストにする var l = new List<IObservable<string>>() { WebRequest.CreateHttp("http://iseebi.half-done.net/test/phone.txt").DownloadStringAsync(), WebRequest.CreateHttp("http://iseebi.half-done.net/test/clientappdev.txt").DownloadStringAsync(), WebRequest.CreateHttp("http://iseebi.half-done.net/test/deviceappdev.txt").DownloadStringAsync(), WebRequest.CreateHttp("http://iseebi.half-done.net/test/powershell.txt").DownloadStringAsync(), }; // ForkJoinで一括処理 Observable.ForkJoin(l) .ObserveOnDispatcher() .Subscribe(res => { foreach (var item in res) { Debug.WriteLine(item); } });
![Page 22: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/22.jpg)
なんでもいいからとにかく非同期に
• とにかくなんでもいいので非同期にしたい場合、以下の組み合わせで何もないところから処理を作り出せる。
– Observable.Defer
– Observable.ToAsync
Observable.Defer(Observable.ToAsync(() => System.Threading.Thread.Sleep(3000))) .ObserveOnDispatcher() .Subscribe(res => Debug.WriteLine("Success!!!"));
![Page 23: 実践 Reactive Extensions](https://reader034.vdocuments.net/reader034/viewer/2022042516/558cf72dd8b42ab64f8b45ed/html5/thumbnails/23.jpg)
まとめ
• Rx 使うと非同期処理が
きれい、かんたん、便利に書けます。
– いくつかの実例をみてご紹介しました。
• Special thanks to @neuecc