Rx入門

33
February 11 th /March 17 th , 2012 鈴木孝明 Hokuriku.NET C# Rx

description

2012/02/11 - 2012/03/17 Hokuriku.NET C# -Rx入門- セッション資料

Transcript of Rx入門

Page 1: Rx入門

February 11th/March 17th, 2012鈴木孝明

Hokuriku.NET C#Rx編

Page 2: Rx入門

Agenda

• Rxの概要

• オブザーバーパターン

• LINQによる記述

• 時間/イベント/非同期のシーケンス化

• HotとCold

• スケジューラの利用

• 今日のまとめ

Page 3: Rx入門

さぁ、Rxの世界へ!!

Rxの概要

Page 4: Rx入門

Rx (Reactive Extensions)とは

• 値群を時間軸に乗ったシーケンスとして捉える

• 時間/イベント/非同期処理をLINQで記述

• .NET 3.5 SP1以降、SL 4以降、WP7で利用可能• 特に非同期APIしかないSilverlight環境で威力を発揮

• Windows Phone 7にのみ標準搭載

• RxJSというJavaScript版もある

• Microsoftの正式なプロジェクト

Page 5: Rx入門

時間軸を基にしたシーケンス

• IObservable<T>は時間軸に乗る非同期な値群• これに乗せられるものはすべて統一的に扱える

• 例) タイマー/イベント/非同期処理

[出典] 連載 : Reactive Extensions (Rx) 入門 - @IT

Page 6: Rx入門

時間軸シーケンスのイメージ

• ベルトコンベアのようなイメージで考える• モノが流れてくる (= IObservable<T>からの発行)

• 不純物を取り除く検査が行われる (= Where)

• 梱包作業が行われる (= Select)

• 配送される (= Subscribe)

Where Select

Page 7: Rx入門

ライブラリの入手

• NuGet Gallery - Rx-Mainより取得

Page 8: Rx入門

ライブラリの入手

• ダウンロードサイトより取得• NuGetが使えない場合

Page 9: Rx入門

Rxの基本はPush通知!!

オブザーバーパターン

Page 10: Rx入門

オブザーバーパターンとは

• 疎結合のためのデザインパターン

• 具象クラス間の依存なしに状態変化を通知する• 例) データ変更→ UI更新

• データがUIを知っている設計は極めて汎用性が低い

• 観測対象 (サブジェクト)と観測者 (オブザーバー)で抽象化

• 一般的にはインターフェース/イベントで実現

Page 11: Rx入門

オブザーバーパターンの構成

Page 12: Rx入門

基本インターフェース

• IObserver<T> : 観測者

• IObservable<T> : 観測対象

• .NET Framework 4で新たに搭載された• .NET 3.5 SP1 / Silverlight 4環境ではRxライブラリが提供する

• Windows Phone 7には標準搭載

OnNext(T value) 状態の変更を通知

OnError(Exception error) エラーの発生を通知

OnCompleted() 完了を通知

Subscribe(IObserver<T> observer) 通知先を登録

Page 13: Rx入門

Push型 vs Pull型

• コネクションを張り、受信待機

• IObservable<T>

• 各々必要に応じて取得しに行く

• IEnumerable<T>

Push型 Pull型

Page 14: Rx入門

IObserver<T>の省略

• IObserver<T>を毎回実装するのは手間• デリゲートを渡すことでオブザーバーの生成を隠蔽

• 隠蔽化によってコードの見え方が変わる• 「IObserver<T>の登録」から「Subscribeで処理」へ

拡張メソッド

Page 15: Rx入門

一人二役なSubject<T>

• IObservable<T>とIObserver<T>の両方を実装

• Rxにおけるイベント

• いくつかの亜種がある

Subject<T> 最も基本的なもの

BehaviorSubject<T> 初期値ありSubject<T>

ReplaySubject<T> 再発行時にリプレイ

AsyncSubject<T> 非同期処理を模倣

Page 16: Rx入門

IObservable<T>の生成メソッド

• Observable静的クラスに数多く提供されている• IObservable<T>を毎回実装するのは手間

• 定型句なものは生成メソッドを使って楽をする

Observable.Range(3, 5);3から始まり1ずつインクリメントされた5つの値を返す

Observable.Repeat(1, 3); 1を3回発行

Observable.Create(observer =>{

observer.OnNext(100);observer.OnCompleted();return () => { … }; // Disposer

};

Subscribeで接続されたオブ

ザーバーに対して直接値を発行

Page 17: Rx入門

宣言的に書ける美しさ!!

LINQによる記述

Page 18: Rx入門

LINQスタイルでの記述

• メソッド形式

• クエリ式形式

Page 19: Rx入門

Where/Selectの内部実装

• IObserver<T>で受ける

• フィルタリング/射影

• IObservable<T>で返却

Source.Where(…).Subscribe(observer);

Page 20: Rx入門

時間軸上の値を統一的に扱おう!!

時間/イベント/非同期のシーケンス化

Page 21: Rx入門

イベントのシーケンス化

• EventHandler/EventHandler<T>形式から生成• Observable.FromEventPatternメソッドを利用

• イベント通知はEventPattern<T>型 (Sender & EventArgs)で行われる

• リフレクションによるオーバーロードもある

• Action<T>/Func<T>など、独自形式から生成• Observable.FromEventメソッドを利用

• 通知する型の形式変換も可能で、非常に柔軟性が高い

Page 22: Rx入門

非同期処理のシーケンス化

• ToAsync/Startメソッドでデリゲートからの生成• 引数を与えたり、戻り値を受けることも可能

• BeginXxx/EndXxx (APMパターン)からの生成• FromAsyncPatternメソッドを利用

• OnCompletedが呼ばれるまでが非同期処理中• 非同期処理の結果はOnCompletedの直前にOnNextで通知される

• 結果が何もない場合はUnit構造体 (voidの代替) が通知される

• 実行スレッドは既定でThreadPool上• GUIアプリの場合、このままではUIに触れないので注意

Page 23: Rx入門

IObservable<T>の性質を知ろう!!

HotとCold

Page 24: Rx入門

Hot vs ColdHot Observable Cold Observable

• すべてのIObserver<T>に対して一度に同じ値を送信

• それぞれのIObserver<T>に対して個別に値を送信

Page 25: Rx入門

Cold to Hot 変換

• 一時的に流れを堰き止める (IConnecableObservable<T>)

• その間に支流を作り、完成したら再放流

Page 26: Rx入門

Rxの柔軟性はココにあり!!

スケジューラの利用

Page 27: Rx入門

スケジューラの概要

• 処理をいつ/どこで実行するかを振り分ける

• IObservable<T>の生成メソッドに設定して利用• 基本的にはメソッドのオーバーロードで指定可能

• 指定しないメソッドは暗黙にデフォルトが設定される

• スレッド切り替え• Observable.ObserveOnメソッドで以降の動作スレッドを変更

• 柔軟性が確保される反面、パフォーマンスが悪い• Observable.RangeはEnumerable.Rangeより数百倍遅い

Page 28: Rx入門

スケジューラの種類

CurrentThreadScheduler 現在実行中のスレッド上で、キューに登録されたものから順に処理

ImmediateScheduler 現在実行中のスレッド上で、即座に実行

NewThreadScheduler それぞれ別スレッドで処理

EventLoopScheduler 指定されたスレッド上で処理

ThreadPoolScheduler スレッドプール上で処理

TaskPoolScheduler 指定されたTaskFactory上で処理

SynchronizationContextScheduler指定されたSynchronizationContextに同期して処理

ControlScheduler指定されたWinFormsコントロールのあるメッセージループで処理

DispatcherScheduler 指定されたDispatcher上で処理

Page 29: Rx入門

ココだけは押さえよう!!

今日のまとめ

Page 30: Rx入門

まとめ

• オブザーバーパターンによるPush通知が基本

• 値群を時間軸に乗ったシーケンスとして捉える

• IObservable<T>とIObserver<T>で実現される

• 時間/イベント/非同期処理をLINQで記述可能• メソッド形式/クエリ式形式どちらでも書ける

• メソッド形式の方ができることは多い

Page 31: Rx入門

まとめ

• HotとColdという性質の違いがある• Hot : すべてのIObserver<T>に対して一度に同じ値を送信

• Cold : それぞれのIObserver<T>に対して個別に値を送信

• スケジューラで柔軟性を提供している• スレッドの切り替え

• 処理順序の変更

• パフォーマンスは大幅に低下する

• .NET 3.5 SP1以降、SL 4以降、WP7で利用可能

Page 32: Rx入門

参考記事

• 連載 : Reactive Extensions (Rx) 入門

• Reactive Extensions入門「まとめ」

• Reactive Extensions再入門

• Rx入門 -インデックス

• neue.cc

Page 33: Rx入門