Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

実践 Reactive Extensions

3,451 views

Published on

Published in: Technology
  • Be the first to comment

実践 Reactive Extensions

  1. 1. 実践 Reactive Extensions 2011/08/27 Silverlight/Phone Quest I 伊勢 シン (Microsoft MVP for Windows Phone)
  2. 2. 自己紹介• 伊勢 シン – Microsoft MVP for Windows Phone (Oct 2010-Sep 2011)• 大阪で働くスマートフォンプログラマ – 目指すは「スマートフォンの万屋」 – iOSアプリをビルドをしながらAndroidアプリのコーディングやったりとか – Windows Phone 7 も少々• 趣味もスマートフォンアプリ開発で – EbIRC – SongTweeter• コミュニティ – スマートフォン勉強会 代表 – Windows Phone Arch 関西スタッフ?
  3. 3. おしながき• Reactive Extension について – 基本的なこと – 書き方の考え方• 実例でみるReactive Extensions – RSSの取得 – ログインが必要なページの先からファイルダウンロード – 複数ページをダウンロードして一括処理 – なんでもいいからとにかく非同期
  4. 4. Reactive Extensions について
  5. 5. そもそもReactive Extensionsって何ぞ• Reactive Extensions (Rx)• LINQの機能を時間軸に拡張するライブラリ – LINQ to SQL, LINQ to Objects に対する LINQ to Events, LINQ to Asynchronous – “WhereでフィルタしてSelectで射影できるならLINQ といえる” – by @neuecc
  6. 6. なにがうれしいの?• 複雑な非同期処理を「直線的に」書ける – 非同期のコードはひたすらネストがつづく – “もはやカオスすぎて頭が痛い” by @neuecc• 例外処理をひとまとめに書ける – Subscribeの第2引数のラムダで一括処理可能• その他各種特典 – 中断処理も簡単。 – リトライ処理 – 処理の待ち合わせ、結合など
  7. 7. “もはやカオスすぎて頭が痛い” 例
  8. 8. そう、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()));
  9. 9. どこでつかえるの?• 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
  10. 10. どうやって使うの?@WP7• 以下のアセンブリを参照 – Microsoft.Phone.Reactive – System.Observable• Rxを使いたいcsファイルのusingに以下を追加 – Microsoft.Phone.Reactive• すべてのはじまりは Observable クラス
  11. 11. そもそもマルチスレッドの基本的な考え方UIスレッド トリガー UI反映 スレッド同期どこか別のスレッド 時間のかかる処理 結果の処理
  12. 12. Rx コードの基本構成 1.トリガー 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, 2.データ処理 Name = elem.Element("Name").Value }) .ObserveOnDispatcher() 3.スレッド同期 .Subscribe(res => { // UI反映 }, err => { // 例外処理 4.UI反映 });
  13. 13. 簡単にRxを書くために• 通信処理系のRxを書くなら RxAsynchronousHelper を使うと便利です。 – 通信を非同期に行うためのRxのおきまり処理を うまくパッケージングしたクラス。あるだけで便利。 – by @neuecc – http://neue.cc/2010/11/26_286.html
  14. 14. 実例で見るReactive Extensionsの使い方
  15. 15. RSSを受信する• 単純な処理の例 – XDocumentの名前空間つけないといけないのだけ なんとかならんかと思っています。
  16. 16. 単純なRSS受信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";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); } });
  17. 17. 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); } });
  18. 18. ダウンロードの結果解析で次のファイルへ• ログインが必要なページなどに有効• SelectManyにすれば、流れに全く関係のない IObservable<T> を新規にメソッドチェーンに 流せる。
  19. 19. テキストに書いてある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); });
  20. 20. 一括ダウンロードしてから処理• 複数のファイルをダウンロードし、 ダウンロード完了後に処理したい場合 – 定義ファイルの一括取得など
  21. 21. 一括ダウンロード// ダウンロード処理を一括でリストにする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); } });
  22. 22. なんでもいいからとにかく非同期に• とにかくなんでもいいので非同期にしたい場合、 以下の組み合わせで何もないところから処理を 作り出せる。 – Observable.Defer – Observable.ToAsyncObservable.Defer(Observable.ToAsync(() =>System.Threading.Thread.Sleep(3000))) .ObserveOnDispatcher() .Subscribe(res => Debug.WriteLine("Success!!!"));
  23. 23. まとめ• Rx 使うと非同期処理が きれい、かんたん、便利に書けます。 – いくつかの実例をみてご紹介しました。• Special thanks to @neuecc

×