Recommended
PDF
PDF
Unity開発で使える設計の話+Zenjectの紹介
PDF
Cinemachineで見下ろし視点のカメラを作る
PDF
PPTX
PDF
PDF
【Unite Tokyo 2019】大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~
KEY
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PDF
PDF
PDF
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
PDF
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PDF
PDF
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
PDF
View Customize Pluginで出来ること
PPTX
PDF
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
PPTX
リアルタイムリモートデバッグ環境によるゲーム開発イテレーションの高速化【DeNA TechCon 2020 ライブ配信】
PDF
PDF
MagicOnion~C#でゲームサーバを開発しよう~
PDF
Reactive extensions入門v0.1
PDF
PPTX
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
PDF
PDF
PDF
PPTX
未来のプログラミング技術をUnityで -UniRx-
PDF
Reactive Programming by UniRx for Asynchronous & Event Processing
More Related Content
PDF
PDF
Unity開発で使える設計の話+Zenjectの紹介
PDF
Cinemachineで見下ろし視点のカメラを作る
PDF
PPTX
PDF
PDF
【Unite Tokyo 2019】大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~
KEY
What's hot
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PDF
PDF
PDF
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
PDF
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PDF
PDF
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
PDF
View Customize Pluginで出来ること
PPTX
PDF
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
PPTX
リアルタイムリモートデバッグ環境によるゲーム開発イテレーションの高速化【DeNA TechCon 2020 ライブ配信】
PDF
PDF
MagicOnion~C#でゲームサーバを開発しよう~
PDF
Reactive extensions入門v0.1
PDF
PPTX
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
PDF
PDF
PDF
Viewers also liked
PPTX
未来のプログラミング技術をUnityで -UniRx-
PDF
Reactive Programming by UniRx for Asynchronous & Event Processing
PPTX
PDF
How to Make Own Framework built on OWIN
PDF
UniRx - Reactive Extensions for Unity
PDF
The History of Reactive Extensions
Similar to Reactive Extensionsで非同期処理を簡単に
PDF
C#次世代非同期処理概観 - Task vs Reactive Extensions
PPTX
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PDF
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
PDF
PDF
.NET最先端技術によるハイパフォーマンスウェブアプリケーション
PDF
PDF
Prism + ReactiveProperty入門
PPTX
An other world awaits you
PPTX
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
PDF
PPTX
PDF
PDF
PDF
PDF
PPTX
PDF
東京Node学園#3 Domains & Isolates
PDF
Windows 8時代のUXを支える非同期プログラミング
PPTX
More from Yoshifumi Kawai
PDF
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
PDF
Deep Dive async/await in Unity with UniTask(UniRx.Async)
PDF
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
PDF
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
PDF
Memory Management of C# with Unity Native Collections
PDF
Building the Game Server both API and Realtime via c#
PDF
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
PDF
The Usage and Patterns of MagicOnion
PDF
Deep Dive async/await in Unity with UniTask(EN)
PDF
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
PDF
NextGen Server/Client Architecture - gRPC + Unity + C#
PDF
A quick tour of the Cysharp OSS
PDF
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
PDF
PDF
How to make the Fastest C# Serializer, In the case of ZeroFormatter
PDF
Implements OpenTelemetry Collector in DotNet
PDF
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
PDF
True Cloud Native Batch Workflow for .NET with MicroBatchFramework
PPTX
RuntimeUnitTestToolkit for Unity(English)
PPTX
RuntimeUnitTestToolkit for Unity
Reactive Extensionsで非同期処理を簡単に 1. 2. Profile
Twitter
=> @neuecc
Blog => http://neue.cc/
HNはneuecc 読むときは“のいえ”と読ませてます
ドメイン繋いだだけなので発音するの考えてなかっ
た(のでccは抜きで←発音しにくいですから)
Microsoft MVP for Visual C#(2011/4-)
WP7で作った物
ReactiveOAuth, Utakotoha
WP7の好きなtheme
light + lime
3. 4. 5. Language INtegrated Query
// クエリ構文
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);
6. 7. LINQのデータソースとは
to Objects to Xml to Sql
配列 XML Database
List<T> (JSON)
Stream
無限リスト
to Events to Asynchronous
TextChanged IO – WebRequest
ジェスチャー Timer – ポーリング
センサー Thread – 長時間かかる処理
MusicPlayer
Reactive Extensions
8. 9. Rxの基本軸は時間
IE<T> length
IE<T>
async
event
IO<T> time
=> IE<T>も乗っかることで「全てのデータソース」が合成可能に!
10. 11. 古き良き同期コード
var req = WebRequest.Create("http://hoge/");
var res = req.GetResponse();
var str = new StreamReader(res.GetResponseStream()).ReadToEnd();
簡単。でも、Silverlight/WP7には同期APIは無い。
UIがブロックされるのダメ絶対
Thread立ててそっちで実行させれば?
まあそうです
でもないものはないのでしょうがない
そのかわり特に気を使わなくても必ずUIノンブロッ
キングになる(※但しCPUヘヴィな処理は除く)
12. しょうがないので非同期で書く
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);
-> EndHoge
非同期はBeginHoge
基本、クロージャ全開で書く
面倒くさいけれど、まあこれぐらいなら?
13. ネストするとかなりヤバい
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);
14. 15. 内側なのは見た目だけ
var req = WebRequest.Create("http://hoge");
req.BeginGetResponse(ar =>
{ 非同期中に起こる例外はEnd時に戻される
try
{
var res = req.EndGetResponse(ar);
var url = new StreamReader(res.GetResponseStream()).ReadToEnd();
var req2 = WebRequest.Create(url);
req2.BeginGetResponse(ar2 => ここの例外をcatchしてない
{
var res2 = req2.EndGetResponse(ar2);
var str = new StreamReader(res2.GetResponseStream()).ReadToEnd();
Dispatcher.BeginInvoke(() => textBlock1.Text = str);
}, null);
} catchできるのは同じ関数のブロック内だけ
catch(WebException e)
{
Dispatcher.BeginInvoke(() => MessageBox.Show(e.ToString()));
}
}, null);
16. もはやカオスすぎて頭痛い
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);
17. Reactive Extensionsを使うと
ネストが消滅し完全フラット
拡張メソッド(後で説明します)
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()));
内部で発生する例外は全てここで扱える
18. 19. 20. 非同期のもと
非同期パターンは概ね二つ
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年ぐらい先)
21. どっちがいいの?
Rxで使うならAPMのほうが相性良い
APMは上から下まで流れてるが、EAPは最後に発火
させなければならない
これはネストする場合に致命的に面倒
// APM
WebRequest.Create("http://hoge")
.GetResponseAsObservable()
.Subscribe();
// EAP
Subscribe後に発火
var wc = new WebClient();
wc.DownloadStringCompletedAsObservable()
.Subscribe();
wc.DownloadStringAsync("http://hoge");
22. 23. FromEvent(FromEventPattern)
戻り値はIEvent<EventArgs>のIO<T>
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<EventHandler,EventArgs>
24. FromAsyncPattern
FromAsyncPatternの戻り値はデリゲート
つまり自分でInvokeするまで実行されない
拡張メソッドにするなら即実行のほうが便利?
Task.Factory.StartNew的なイメージで
public static IObservable<WebResponse>
GetResponseAsObservable(this WebRequest request)
{
return Observable.FromAsyncPattern<WebResponse>(
request.BeginGetResponse, request.EndGetResponse)
.Invoke();
}
25. 26. 最初の例もこんなにスッキリ
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()));
27. 28. 29. ところでキャンセルしたい
// 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();
30. 例外処理は?
何も書かない
例外はcatchせずスローされてくる
SubscribeのonErrorに書く
Rxのチェーンで発生した例外を全てcatchする
ここに空のものを書けば例外無視が成立とかも
※Tips:一部メソッドが間に挟まれていると(Publishなど)
場合によってはcatchされなくなることも(Publishは内部
で自前でSubscribeしているためチェーンが途切れてる)
Catchメソッドを使う
例外の型を指定した通常のtry-catchに近いもの
戻り値にEmptyを返せば終了、何か別の値を返せばそ
れを代替として流すということになる
31. 基本的なのはこの3つ
// 何も書かないので例外がスローされてくる
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);
32. 33. 34. SelectMany + Zip - 合成の例
AsyncA AsyncB
Result
AsyncC
AsyncA().SelectMany(a => AsyncB(a))
.Zip(AsyncC(), (b, c) => new { b, c });
35. ForkJoin - 並列同時実行
AsyncA
AsyncB
Result
AsyncC
AsyncD
Observable.ForkJoin(AsyncA(), AsyncB(), AsyncC(), AsyncD())
.Select(xs => new { a=xs[0], b=xs[1], c=xs[2], d=xs[3] });
36. 多重from(SelectMany)
AsyncA AsyncB AsyncC Result
var asyncQuery = from a in AsyncA()
from b in AsyncB(a)
from c in AsyncC(a, b)
select new { a, b, c };
37. 38. 39. 40. 41. どんな時に使えるの?
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(); // なにか処理するなり例外処理入れるなり
42. 43. 44. 45. 46. 公式見るのがいいよやっぱり
Data Developer Center - Rx
http://msdn.microsoft.com/en-us/data/gg577609
二つのドキュメントが出ています
Hands-on-Lab
チュートリアル式で触りながら分かりやすく
まず見て欲しい
Design Guidelines
マニュアルみたいなもの
更に深くへ
47.