Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Reactive Extensionsで WP7の非同期処理を簡単に
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Yoshifumi Kawai
May 21, 2011
Technology
74
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Reactive Extensionsで WP7の非同期処理を簡単に
Yoshifumi Kawai
May 21, 2011
More Decks by Yoshifumi Kawai
See All by Yoshifumi Kawai
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
4
2.8k
.NET for Android with Native AOT Built with Cursor
neuecc
0
6.6k
CysharpのOSS群から見るModern C#の現在地
neuecc
2
47k
R3のコードから見る実践LINQ実装最適化・コンカレントプログラミング実例
neuecc
5
57k
.NETの非同期戦略とUnityとの相互運用
neuecc
3
56k
他言語がメインの場合のRustの活用法 - csbindgenによるC# x Rust FFI実践事例
neuecc
7
42k
Modern High Performance C# 2023 Edition
neuecc
4
16k
CEDEC 2023 モダンハイパフォーマンスC# 2023 Edition
neuecc
9
120k
C#11 による世界最速バイナリシリアライザー「MemoryPack」の作り方
neuecc
1
42k
Other Decks in Technology
See All in Technology
すぐできる衛星通信対応 あとは山奥に行くだけ
tatetate55
0
140
あけおめLINE 傾向とその対策
nasa9084
0
180
LLMに渡さなかった仕事
nanaism
0
1.1k
サーバーレスをどこまで使う? WebRTC対戦ゲームで選んだVPSとの共存設計
kaidouji85
0
190
Von-Neumann Machines, Dreams & The Futures of IT
ufried
0
110
AI de Idea
kawaguti
PRO
2
130
顧客に向き合う開発組織へ。リアーキテクチャとフィーチャーチーム化で挑む組織改革
safie
0
2.1k
AIは推し活である。
kurazuuuuuu
1
860
越境するなら専門用語を使うな高校校歌 / If you wanna cross border, you shouldn't use jargon
vtryo
0
150
「どのログを見ればいい?」 から始めた サーバーレス障害解析
y_waka1
1
100
「守り」で活用するオンデバイスLLM 〜写ってはいけないを総力戦で防ぐ〜 / iOSDC Japan 2026
nakamuuu
0
180
負債のメタファと2026年 / Debt Metaphor in Agentic Engineering Age 202609 Edition
twada
PRO
10
4.3k
Featured
See All Featured
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
430
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
New Earth Scene 8
popppiees
4
2.6k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Making Projects Easy
brettharned
120
6.8k
How to build a perfect <img>
jonoalderson
1
6k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
810
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
3
4.3k
Automating Front-end Workflow
addyosmani
1369
210k
The Pragmatic Product Professional
lauravandoore
37
7.4k
What's in a price? How to price your products and services
michaelherold
247
13k
Transcript
Reactive Extensionsで WP7の非同期処理を簡単に @neuecc – 2011/5/21
Twitter => @neuecc Blog => http://neue.cc/ HNはneuecc
読むときは“のいえ”と読ませてます ⚫ ドメイン繋いだだけなので発音するの考えてなかっ た(のでccは抜きで←発音しにくいですから) Microsoft MVP for Visual C#(2011/4-) WP7で作った物 ⚫ ReactiveOAuth, Utakotoha WP7の好きなtheme ⚫ light + lime Profile
LINQの概要/LINQとしてのReactive Extensions 非同期処理の面倒さと如何にRxが癒すか .NETにおける非同期パターンの説明 Rxの基本(購読, キャンセル,
例外処理) 非同期処理で使うRxのメソッド概略 作った物紹介 Agenda
Linq to Introduction
// クエリ構文 var query = from x in source where
x % 2 == 0 select x * x; // メソッド構文 var query = source .Where(x => x % 2 == 0) .Select(x => x * x); Language INtegrated Query
データソースを統一的な書法で処理できる WhereでフィルタしてSelectで射影できるならそれ はLINQって言えます! SQL関係ないし、C#も飛び越えて生きる概念 JavaScript移植もあるしね ⚫
linq.js – http://linqjs.codeplex.com/ ⚫ RxJS(Reactive Extensions for JavaScript) LINQって何?
Reactive Extensions LINQのデータソースとは to Objects 配列 List<T> Stream 無限リスト to
Xml XML (JSON) to Sql Database to Events TextChanged ジェスチャー センサー MusicPlayer to Asynchronous IO – WebRequest Timer – ポーリング Thread – 長時間かかる処理
Reactive Extensions = Linq to Events Linq to Asynchronous LINQにおけるデータソースの拡張
……というだけじゃない 時間という軸を中心にした基盤
Rxの基本軸は時間 IE<T> length IO<T> time event async IE<T> => IE<T>も乗っかることで「全てのデータソース」が合成可能に!
Async Programming Blues
var req = WebRequest.Create("http://hoge/"); var res = req.GetResponse(); var str
= new StreamReader(res.GetResponseStream()).ReadToEnd(); 簡単。でも、Silverlight/WP7には同期APIは無い。 ⚫ UIがブロックされるのダメ絶対 Thread立ててそっちで実行させれば? ⚫ まあそうです ⚫ でもないものはないのでしょうがない ⚫ そのかわり特に気を使わなくても必ずUIノンブロッ キングになる(※但しCPUヘヴィな処理は除く) 古き良き同期コード
var req = WebRequest.Create("http://hoge"); req.BeginGetResponse(ar => { var res =
req.EndGetResponse(ar); var str = new StreamReader(res.GetResponseStream()) .ReadToEnd(); Dispatcher.BeginInvoke(() => MessageBox.Show(str)); }, null); 非同期はBeginHoge -> EndHoge 基本、クロージャ全開で書く 面倒くさいけれど、まあこれぐらいなら? しょうがないので非同期で書く
var req = WebRequest.Create("http://hoge"); req.BeginGetResponse(ar => { var res =
req.EndGetResponse(ar); var url = new StreamReader(res.GetResponseStream()) .ReadToEnd(); var req2 = WebRequest.Create(url); req2.BeginGetResponse(ar2 => { var res2 = req2.EndGetResponse(ar2); var str = new StreamReader(res2.GetResponseStream()) .ReadToEnd(); Dispatcher.BeginInvoke(() => MessageBox.Show(str)); }, null); }, null); ネストするとかなりヤバい
WP7ではネットワーク周りのコードでは100%例外 発生の可能性がある 圏外だったり通信が超低速だったりすると? ⚫ Hello, Timeout. ⚫ 山崎春のWebException祭り
⚫ 何の手立てもしないとアプリ落ちるよ 予期される例外だし、固有の後処理もあるだろう し、復帰可能にすべきなので、その場その場で catchして始末するのが無難 通信箇所に例外処理は必須
var req = WebRequest.Create("http://hoge"); req.BeginGetResponse(ar => { try { var
res = req.EndGetResponse(ar); var url = new StreamReader(res.GetResponseStream()).ReadToEnd(); var req2 = WebRequest.Create(url); req2.BeginGetResponse(ar2 => { var res2 = req2.EndGetResponse(ar2); var str = new StreamReader(res2.GetResponseStream()).ReadToEnd(); Dispatcher.BeginInvoke(() => textBlock1.Text = str); }, null); } catch(WebException e) { Dispatcher.BeginInvoke(() => MessageBox.Show(e.ToString())); } }, null); 内側なのは見た目だけ 非同期中に起こる例外はEnd時に戻される ここの例外をcatchしてない catchできるのは同じ関数のブロック内だけ
var req = WebRequest.Create("http://hoge"); req.BeginGetResponse(ar => { try { var
res = req.EndGetResponse(ar); var url = new StreamReader(res.GetResponseStream()).ReadToEnd(); var req2 = WebRequest.Create(url); req2.BeginGetResponse(ar2 => { try { var res2 = req2.EndGetResponse(ar2); var str = new StreamReader(res2.GetResponseStream()).ReadToEnd(); Dispatcher.BeginInvoke(() => MessageBox.Show(str)); } catch (WebException e) { Dispatcher.BeginInvoke(() => MessageBox.Show(e.ToString())); } }, null); } catch (WebException e) { Dispatcher.BeginInvoke(() => MessageBox.Show(e.ToString())); } }, null); もはやカオスすぎて頭痛い
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())); Reactive Extensionsを使うと 内部で発生する例外は全てここで扱える ネストが消滅し完全フラット 拡張メソッド(後で説明します)
ネストがなくなって平らに 統一的な例外処理が可能 + その他の機能もいっぱい ⚫ リトライ処理 ⚫
イベントやシーケンスとの合成など Rxを使うことの利点
Asynchronous Patterns
非同期パターンは概ね二つ ⚫ APM(Asynchronous Programming Model) ⚫ BeginXxx-EndXxx ⚫ WebRequest.BeginGetResponseとか
⚫ EAP(Event-based Asynchronous Pattern) ⚫ XxxAsync-XxxCompleted ⚫ WebClient.DownloadStringAsync/Copletedとか 将来的には? ⚫ Rx(WP7では標準搭載ですが.NET4ではまだ) ⚫ Task(.NET4では標準搭載ですがWP7ではまだ) ⚫ C# 5.0 Async(まだCTP, 恐らく2年ぐらい先) 非同期のもと
Rxで使うならAPMのほうが相性良い APMは上から下まで流れてるが、EAPは最後に発火 させなければならない これはネストする場合に致命的に面倒 // APM WebRequest.Create("http://hoge")
.GetResponseAsObservable() .Subscribe(); // EAP var wc = new WebClient(); wc.DownloadStringCompletedAsObservable() .Subscribe(); wc.DownloadStringAsync("http://hoge"); どっちがいいの? Subscribe後に発火
APM, WebRequest->WebResponseはプリミティブ すぎて、一々Stream扱ったり面倒くさい WebClientのDownloadString的なのが欲しい なら拡張メソッドで自作すれば解決 FromEventやFromAsyncPatternは定型句なので、こ
ちらも拡張メソッドで隔離するのがお薦め 拡張メソッドのすゝめ
public static IObservable<IEvent<DownloadStringCompletedEventArgs>> DownloadStringCompletedAsObservable(this WebClient webClient) { return Observable.FromEvent< DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>( h => h.Invoke, // おまじない h => webClient.DownloadStringCompleted += h, h => webClient.DownloadStringCompleted -= h); } FromEvent(FromEventPattern) 戻り値はIEvent<EventArgs>のIO<T> FromEvent<EventHandler,EventArgs>
FromAsyncPatternの戻り値はデリゲート ⚫ つまり自分でInvokeするまで実行されない 拡張メソッドにするなら即実行のほうが便利? Task.Factory.StartNew的なイメージで public static
IObservable<WebResponse> GetResponseAsObservable(this WebRequest request) { return Observable.FromAsyncPattern<WebResponse>( request.BeginGetResponse, request.EndGetResponse) .Invoke(); } FromAsyncPattern
Stringが戻ったほうが便利ですよね POSTなども同じように作っておくと楽になる public static IObservable<string> DownloadStringAsync(this WebRequest request)
{ return request.GetResponseAsObservable() .Select(res => { using (var stream = res.GetResponseStream()) using (var sr = new StreamReader(stream)) { return sr.ReadToEnd(); } }); } DownloadStringAsync(の自作)
Rxが提供してくれているのは基本的な道具 Rxは「分離しやすい」のも特徴的なメリット <T>への拡張メソッドや、IO<T>->IO<T>の拡張メ ソッドなどを作って、すっきりさせよう WebRequest.Create("http://hoge") .DownloadStringAsync() .SelectMany(s
=> WebRequest.Create(s).DownloadStringAsync()) .ObserveOnDispatcher() .Subscribe( s => MessageBox.Show(s), e => MessageBox.Show(e.ToString())); 最初の例もこんなにスッキリ
Basics of Rx
Microsoft.Phone.Reactiveを参照する System.Observableを参照する ⚫ WP7には標準搭載 ⚫ NET4版は別途インストールしてSystem.Reactiveを 定形的な流れは
FromEvent/FromAsyncして(IO<T>の生成) SelectなりWhereなりLINQでデータを加工して ObserveOnDispatcherして(値をUIスレッドに戻す) Subscribeする 書き方の基本
// Subscribeの戻り値はIDisposableなので、Disposeすればおk var disposable = AsyncMethod().Subscribe(); disposable.Dispose(); // イベントの場合はデタッチになるよ var
buttonClick = button.ClickAsObservable().Subscribe(); buttonClick.Dispose(); // Listに入れてまとめてDisposeとか var disposables = new List<IDisposable>(); disposable.Add(button.ClickAsObservable().Subscribe()); disposable.Add(button.ClickAsObservable().Subscribe()); disposable.ForEach(d => d.Dispose()); // IList<IDisposable>はCompositeDisposableというのもある var disposables = new CompositeDisposable(); disposable.Dispose(); ところでキャンセルしたい
何も書かない ⚫ 例外はcatchせずスローされてくる SubscribeのonErrorに書く ⚫ Rxのチェーンで発生した例外を全てcatchする ⚫ ここに空のものを書けば例外無視が成立とかも
⚫ ※Tips:一部メソッドが間に挟まれていると(Publishなど) 場合によってはcatchされなくなることも(Publishは内部 で自前でSubscribeしているためチェーンが途切れてる) Catchメソッドを使う ⚫ 例外の型を指定した通常のtry-catchに近いもの ⚫ 戻り値にEmptyを返せば終了、何か別の値を返せばそ れを代替として流すということになる 例外処理は?
// 何も書かないので例外がスローされてくる WebRequest.Create("http://hoge") .DownloadStringAsync() .Subscribe(Debug.WriteLine); // SubscribeのonErrorで全てcatch WebRequest.Create("http://hoge") .DownloadStringAsync() .Subscribe(Debug.WriteLine,
e => { }); // CatchでWebExceptionだけcatch WebRequest.Create("http://hoge") .DownloadStringAsync() .Catch((WebException e) => Observable.Empty<string>()) .Subscribe(Debug.WriteLine); 基本的なのはこの3つ
Compose Patterns
AsyncA AsyncB SelectMany - 直列の結合 AsyncA Zip - 並列の結合 AsyncB
Result
AsyncA AsyncB AsyncC Result AsyncA().SelectMany(a => AsyncB(a)) .Zip(AsyncC(), (b, c)
=> new { b, c }); SelectMany + Zip - 合成の例
AsyncA AsyncC AsyncD Result Observable.ForkJoin(AsyncA(), AsyncB(), AsyncC(), AsyncD()) .Select(xs =>
new { a=xs[0], b=xs[1], c=xs[2], d=xs[3] }); ForkJoin - 並列同時実行 AsyncB
var asyncQuery = from a in AsyncA() from b in
AsyncB(a) from c in AsyncC(a, b) select new { a, b, c }; 多重from(SelectMany) AsyncA AsyncB AsyncC Result
Conclusion
FromEvent/Asyncは拡張メソッドで隔離 ついでにReadToEndなんかも隔離 とりあえずSubscribeの前にObserveOnDispatcher onErrorとCatchで例外をコントロール 色々な合成メソッドで流れをコントロール
もう非同期なんて怖くない! Rxで書くと実は同期で書くよりも柔軟 むしろもう同期でなんて書きたくない! まとめ
Real World Rx
http://reactiveoauth.codeplex.com/ TwitterとかのOAuth認証/通信用ライブラリ 以下のWP7アプリで使われています! ⚫ SongTweeter @iseebi ⚫
NumberPush @mitsuba_tan ⚫ Utakata TextPad @kaorun ⚫ HirganaTwit @hatsune_ ReactiveOAuth
Twitterクライアントを作るわけではないけれど、 ステータスだけTwitterに投稿したい、などはよく あること(特に最近は何でもTwitterだし) new OAuthClient(ConsumerKey, ConsumerSecret, accessToken) { MethodType
= MethodType.Post, Url = "http://api.twitter.com/1/statuses/update.xml", Parameters = { { "status", "ここに投稿する文章" } } } .GetResponseText() // 投稿して、戻り値を得る .Select(XElement.Parse) // xmlの場合はパースしたいよね .Subscribe(); // なにか処理するなり例外処理入れるなり どんな時に使えるの?
WP7だけじゃなく.NET4/SL4向けもあり コードの99%をWP7と共有している ⚫ 残り1%は最近の更新で.NET版Rxが一部WP7版と互換 なくなったため Rxをベースに置くと、コードの可搬性が圧倒的に 高まる
機能面でもRxにタダ乗り出来るので(エラー・リト ライ・タイムアウトなど全部Rxにおまかせ) ライブラリ本体はシンプルなコードのままで強力 な機能を持てる ポータビリティ
http://utakotoha.codeplex.com/ 再生中の曲に応じて日本語歌詞を表示する マーケットプレイスで公開中(Free) ソースコードも公開中 Utakotoha
コードは無理やり全部Rxで割と実験的 GUI周りは強引でボロボロで酷い イベント周りなどは面白く仕上がったかも Modelを別に立てた.NET4クラスライブラリにリン クで参照することによりMSTestでユニットテスト
Molesというモックライブラリを使ってWP7のイベ ント自体を乗っ取り(音楽再生の情報をテストのた めに任意に生成したり) 上手くいってるかはノーコメント コードの中身
Deep Dive Rx
Data Developer Center - Rx http://msdn.microsoft.com/en-us/data/gg577609 二つのドキュメントが出ています
⚫ Hands-on-Lab ⚫ チュートリアル式で触りながら分かりやすく ⚫ まず見て欲しい ⚫ Design Guidelines ⚫ マニュアルみたいなもの ⚫ 更に深くへ 公式見るのがいいよやっぱり
ねぇよんなもん うちのサイトでも見てください:) ⚫ http://neue.cc/ ⚫ http://neue.cc/category/rx 日本語情報は?