windows 8時代のuxを支える非同期プログラミング

48
時代の を支える 非同期プログラミング グレープシティ株式会社 八巻 雄哉

Upload: yuya-yamaki

Post on 12-Nov-2014

2.878 views

Category:

Technology


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Windows 8時代のUXを支える非同期プログラミング

時代の を支える非同期プログラミング

グレープシティ株式会社

八巻雄哉

Page 2: Windows 8時代のUXを支える非同期プログラミング

本日のお話し

2

Page 3: Windows 8時代のUXを支える非同期プログラミング

これまで

非同期処理の必要性、および需要

非同期処理実装の難易度

低 高

低 高

3

Page 4: Windows 8時代のUXを支える非同期プログラミング

これから( 時代)

非同期処理の必要性、および需要

非同期処理実装の難易度

低 高

低 高

4

Page 5: Windows 8時代のUXを支える非同期プログラミング

“非同期処理”って何?

5

Page 6: Windows 8時代のUXを支える非同期プログラミング

“非同期処理”って何?

同期処理

一つの処理が終わるまで次の処理が行われない

非同期処理

前の処理とは関係なく次の処理が行われる

6

Page 7: Windows 8時代のUXを支える非同期プログラミング

人間とプログラムの違い

人間は意識しなくとも非同期的に動いている

プログラムは何もしないと同期的にしか動かない

この違いがユーザーエクスペリエンスの低下を生む

7

Page 8: Windows 8時代のUXを支える非同期プログラミング

もしも人間がプログラムのように動いたら

レストランの業務をプログラム化してみる

8

Page 10: Windows 8時代のUXを支える非同期プログラミング

「 」イベントハンドラ

10

Page 11: Windows 8時代のUXを支える非同期プログラミング

「注文が決定する」イベントハンドラ

注文が決定する注文決定イベント引数

注文 注文を得る テーブル番号

材料 材料を得る注文

レシピ レシピを得る注文

料理 レシピ作成する材料

提供する 料理 テーブル番号

11

Page 12: Windows 8時代のUXを支える非同期プログラミング

料理が完成するまでは一切何もできません

「呼び出しボタン」 を押す 注文が決定する 注文決定イベント引数

注文 注文を得る テーブル番号

材料 材料を得る 注文

レシピ レシピを得る 注文

料理 レシピ作成する 材料

提供する 料理 テーブル番号

料理が 運ばれてくる

12

お客さん 料理店の人

Page 13: Windows 8時代のUXを支える非同期プログラミング

ボタンを押すと結果が返るまで は応答不能

ボタン を押す 注文が決定する 注文決定イベント引数

注文 注文を得る テーブル番号

材料 材料を得る 注文

レシピ レシピを得る 注文

料理 レシピ作成する 材料

提供する 料理 テーブル番号

結果がUI上に 表示される

13

ユーザー メインスレッド

Page 14: Windows 8時代のUXを支える非同期プログラミング

非同期処理の種類

① 非ブロッキング (非同期 )

をブロックしないための非同期処理

② 並列処理(計算)

データ並列

タスク並列

14

Page 15: Windows 8時代のUXを支える非同期プログラミング

非同期化する方法

15

Page 16: Windows 8時代のUXを支える非同期プログラミング

非同期化する方法

マルチスレッド化

メインスレッドはユーザーの入力( からの指示)を待ち受けるためのスレッドとし、料理を作る処理は別のスレッドにお願いする

レストランの例では

接客専任のホールスタッフを雇う

16

Page 17: Windows 8時代のUXを支える非同期プログラミング

スレッドを使用SynchronizationContext ctx = SynchronizationContext.Current;

ThreadPool.QueueUserWorkItem(_ =>

{

var 注文 = 注文を得る(e.テーブル番号);

var 材料 = 材料を得る(注文);

var レシピ = レシピを得る(注文);

var 料理 = レシピ.作成する(材料);

ctx.Post(state =>

{

提供する(料理, e.テーブル番号);

}, 料理);

});

17

Page 18: Windows 8時代のUXを支える非同期プログラミング

非同期プログラミングの難しさ

18

Page 19: Windows 8時代のUXを支える非同期プログラミング

①新しくスレッドを生成するのは思った以上にコストがかかる

注文を受ける度に新しくスレッドを生成するのは効率が悪い

ではあらかじめ用意されたスレッドをできる限り再利用するスレッドプールという仕組みがある

レストランの例では

新しく人を雇うのには意外とコストがかかる

19

Page 20: Windows 8時代のUXを支える非同期プログラミング

②順序やタイミングが大切な処理は必ず存在する

別スレッドで実行した処理の継続処理、および完了待ち

お互いがスレッドの完了を待ち続けるデッドロックや共有メモリへのアクセスによる競合状態

レストランの例では

一人のときは全部自分がやっていたから問題が起きなかったが、二人以上では協調して動かなければならない

20

Page 21: Windows 8時代のUXを支える非同期プログラミング

③ コンポーネントへのアクセスは、その コンポーネントを作成したスレッドで行わなければならない実行結果を 上に表示するといった場合、

必ず スレッドに処理を委譲する必要がある

レストランの例では

料理人が自分で料理をお客さんに出したほうが早いのに、運ばせてくれない

21

Page 22: Windows 8時代のUXを支える非同期プログラミング

④スレッドプログラミングの怖さはテストのしにくさ

回動作したから正しいという保証もないし、回動作したから正しいという保証もない

レストランの例では

人を管理するのはとても大変で、想像もしない行動を起こすこともある

22

Page 23: Windows 8時代のUXを支える非同期プログラミング

非推奨

よほどのことがない限り、直接スレッドをどうこうしようと思ってはいけない

マイクロソフト株式会社コンサルティングサービス統括本部プリンシパルコンサルタント赤間信幸氏いわく

やはり個人的におすすめしたいのは、マルチスレッドアプリケーションはなるべく作らない。これに尽きます。

23

Page 24: Windows 8時代のUXを支える非同期プログラミング

.NETにおける非同期処理簡便化

24

Page 25: Windows 8時代のUXを支える非同期プログラミング

ライブラリとコンパイラの進化

非同期動作を公開するためのパターン

IAsyncResultパターン(.NET 1.0~)

イベントベースの非同期パターン(.NET 2.0~)

タスクベースの非同期パターン(.NET 4.0 ~ )

タスクベースの非同期パターンを 簡便に記述するための新たな構文

async/await構文(.NET 4.5、Windows Runtime)

25

Page 26: Windows 8時代のUXを支える非同期プログラミング

タスク並列ライブラリ

26

Page 27: Windows 8時代のUXを支える非同期プログラミング

タスク並列ライブラリ

( )

名前空間

名前空間

タスクとして思考すればよく、スレッドに対する深い知識は不要

タスク並列ライブラリを使うことで、処理が簡略化されるだけでなく、効率よく実行できる

非同期処理を簡単に操作、および構成するメソッドを持つ

Page 28: Windows 8時代のUXを支える非同期プログラミング

タスクを使用var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();

Task<Meal> task = Task.Factory.StartNew(() =>

{

var 注文 = 注文を得る(e.テーブル番号);

var 材料 = 材料を得る(注文);

var レシピ = レシピを得る(注文);

var 料理 = レシピ.作成する(材料);

return 料理;

});

task.ContinueWith(t =>

{

提供する(t.Result, e.テーブル番号);

}, uiTaskScheduler);

28

Page 29: Windows 8時代のUXを支える非同期プログラミング

タスクベースの非同期パターン

29

Page 30: Windows 8時代のUXを支える非同期プログラミング

タスクベースの非同期パターン

( )

標準クラスライブラリには、時間のかかる処理においてタスクベースの非同期メソッドが用意されている

を返す 、およびメソッド

Page 31: Windows 8時代のUXを支える非同期プログラミング

タスクの継続と待機

継続

待機

メソッド一つのタスクに対して、継続タスクを指定する

メソッド継続元タスクが複数存在する状態で、その全てが完了した場合に継続する

メソッド継続元タスクが複数存在する状態で、そのどれかが完了した場合に継続する

メソッドタスクを待機させる

メソッド指定された複数のタスクを待機させる

メソッド指定された複数のタスクの内、どれかが完了するまで待機させる

Page 32: Windows 8時代のUXを支える非同期プログラミング

肉を焼いてから野菜を切るvar ターキー = (肉)材料[0];

味をつける(ターキー);

オーブンで焼く(40, ターキー);

var サラダ用野菜 = (野菜)材料[1];

切る(サラダ用野菜);

皿に盛り付ける(サラダ用野菜);

皿に盛り付ける(ターキー);

32

Page 33: Windows 8時代のUXを支える非同期プログラミング

肉を焼いている間に野菜を切るvar ターキー = (肉)材料[0];

味をつける(ターキー);

Task task1 = オーブンで焼くAsync(40, ターキー);

var サラダ用野菜 = (野菜)材料[1];

Task task2 = 切るAsync(サラダ用野菜);

task2.ContinueWith(_ =>

{

Task task3 = 皿に盛り付けるAsync(サラダ用野菜);

});

Task.WaitAll(task1, task2);

皿に盛り付ける(ターキー);

33

Page 34: Windows 8時代のUXを支える非同期プログラミング

async/await構文

34

Page 35: Windows 8時代のUXを支える非同期プログラミング

構文

メソッドに 修飾子、非同期処理(タスクベースの非同期版メソッド)の手前に キーワードをつけるだけ

同期処理とほぼ同様のコードをコンパイラが機械的にタスクを使った非同期処理へと変換してくれる

スレッドをブロックすることなくメソッドの実行を一時停止したり再開したりできるポイントをメソッドに埋め込む

Page 36: Windows 8時代のUXを支える非同期プログラミング

同期版

注文が決定する注文決定イベント引数

注文 注文を得る テーブル番号

材料 材料を得る注文

レシピ レシピを得る注文

料理 レシピ作成する材料

提供する料理 テーブル番号

36

Page 37: Windows 8時代のUXを支える非同期プログラミング

非同期版

注文が決定する注文決定イベント引数

var 注文 = await 注文を得るAsync(e.テーブル番号);

var 材料 = await 材料を得るAsync(注文);

var レシピ = await レシピを得るAsync(注文);

var 料理 = await レシピ.作成するAsync(材料);

提供する(料理, e.テーブル番号);

37

Page 38: Windows 8時代のUXを支える非同期プログラミング

async/await構文使用時の実行順序

38

Page 39: Windows 8時代のUXを支える非同期プログラミング

同期版メソッド

39

private void Button_Click_1(object sender, RoutedEventArgs e)

{

Download();

debugList.Items.Add("コアラ");

}

private void Download()

{

debugList.Items.Add("パンダ");

HeavyTask();

debugList.Items.Add("うさぎ");

}

Page 40: Windows 8時代のUXを支える非同期プログラミング

同期版の実行順序

40

Download();

debugList.Items.Add("パンダ");

HeavyTask();

debugList.Items.Add("うさぎ");

debugList.Items.Add("コアラ");

private void Download()

private void Button_Click_1(…)

時間のかかる処理

Page 41: Windows 8時代のUXを支える非同期プログラミング

非同期版メソッド

41

private void Button_Click_1(object sender, RoutedEventArgs e)

{

Download();

debugList.Items.Add("コアラ");

}

private async void Download()

{

debugList.Items.Add("パンダ");

await HeavyTaskAsync();

debugList.Items.Add("うさぎ");

}

Page 42: Windows 8時代のUXを支える非同期プログラミング

非同期版の実行順序

42

Download();

debugList.Items.Add("パンダ");

debugList.Items.Add("コアラ");

debugList.Items.Add("うさぎ");

await HeavyTaskAsync();

中断

再開

private async void Download()

private void Button_Click_1(…)

時間のかかる処理

Page 43: Windows 8時代のUXを支える非同期プログラミング

非同期プログラミングの重要性

43

Page 44: Windows 8時代のUXを支える非同期プログラミング

高まる非同期処理の重要性

① タッチ における応答継続の重要性

“ ” (指に吸い付く )

タッチ は基本的に全画面

② ネット世代における

ブラウザーは常に非同期

③ マルチコア時代

ムーアの法則の恩恵を受けるためにも

44

Page 45: Windows 8時代のUXを支える非同期プログラミング

高まる非同期の必然性

側から

の場合非同期版メソッドが用意されているのは、

主に通信&データにおける のみ

スタイルアプリ/ の場合

実行に ミリ秒以上の時間がかかる可能性のあるメソッドはすべて非同期化されている

システム( )側から

では、メインスレッドが 秒以上応答しなければ強制終了

45

Page 46: Windows 8時代のUXを支える非同期プログラミング

Metroスタイルアプリ用のWinRT API

基礎部分

認証 暗号化 グローバリゼーション

.NET Win32 アプリの 有効期間

通信 & データ

コントラクト XML Web

ネットワーク 通知

ローカル & クラウドストレージ メディア

キャプチャ

リモート再生

デバイス

センサー

地理位置情報

ポータブルデバイス

NFC

ユーザー インターフェイス

HTML5/CSS XAML DirectX コントロール

入力 アクセシビリティ 印刷

データバインディング

タイル

ストリーム

バックグラウンド転送

SVG

AtomPub

SMS

プリンター

視覚効果

コード変換

46

Page 47: Windows 8時代のUXを支える非同期プログラミング

時代に向けて

スタイルアプリ開発では多くの処理を非同期にせざるを得ない

時代はフリーズしない が当たり前

スタイルアプリの開発では、、 、 言語( / )

の 種類がありますが、/ のように同期操作と

ほぼ同等の記述ができるのは 言語だけ

47

Page 48: Windows 8時代のUXを支える非同期プログラミング