Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
New Asynchronous Feature for C# 5.0
Search
Ktz
September 30, 2012
Programming
1
440
New Asynchronous Feature for C# 5.0
async / awaitというC# 5.0から備わった新機能についての解説
async / awaitを使ったことによる失敗体験
Ktz
September 30, 2012
Tweet
Share
More Decks by Ktz
See All by Ktz
DuckDB雑紹介(1.1対応版)@DuckDB座談会
ktz
30
9.8k
DuckDB雑紹介
ktz
9
4.7k
Other Decks in Programming
See All in Programming
eBPFを用いたAIネットワーク監視システム論文の実装 / eBPF Japan Meetup #4
yuukit
3
530
❄️ tmux-nixの実装を通して学ぶNixOSモジュール
momeemt
1
120
Rethinking Data Access: The New httpResource in Angular
manfredsteyer
PRO
0
200
Use Perl as Better Shell Script
karupanerura
0
590
複雑なフォームを継続的に開発していくための技術選定・設計・実装 #tskaigi / #tskaigi2025
izumin5210
12
6.1k
『Python → TypeScript』オンボーディング奮闘記
takumi_tatsuno
1
120
コードに語らせよう――自己ドキュメント化が内包する楽しさについて / Let the Code Speak
nrslib
5
740
バリデーションライブラリ徹底比較
nayuta999999
1
320
知識0からカンファレンスやってみたらこうなった!
syossan27
5
320
TypeScript エンジニアが Android 開発の世界に飛び込んだ話
yuisakamoto
6
880
"使いづらい" をリバースエンジニアリングする UI の読み解き方
rebase_engineering
0
100
ruby.wasmとWebSocketで遊ぼう!
lnit
0
150
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
269
20k
Mobile First: as difficult as doing things right
swwweet
223
9.6k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Facilitating Awesome Meetings
lara
54
6.4k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
21k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
15
880
Making Projects Easy
brettharned
116
6.2k
What's in a price? How to price your products and services
michaelherold
245
12k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.7k
Faster Mobile Websites
deanohume
307
31k
Transcript
1. 非同期処理ってむずかしい (><)¶
1.1. はじめに¶ • C# 5.0から採用された • async / await •
手軽に非同期処理が書ける
1.2. わたし¶ おなまえ たむらかずひこ twitter ktz_alias • ひよっこC#使い (Lv.1) •
gitムズ過ぎ • bzrかわいいよbzr
1.3. async の決まり事¶ • 戻り値がTaskまたはvoid • コード例は後で
1.4. async Task¶ • 完了するまで後続の処理を止めてくれる • その間は一旦、呼び出し元へ戻る • 呼び出し元で結果欲しい場合に使う
1.5. async Task¶ public async void Foo() { var bar
= await BarAsync(); // 上の結果待ってから続行 return await BazzAsync(bar); } public async Task<int> BarAsync() { ... }
1.6. async void¶ • 結果を待たず、呼び出し元に戻る • 投げっ放しジャーマン
1.7. async void¶ public async void Foo() { await BarAsync();
// 上の結果待たずに続行 await BazzAsync(); } public async void BarAsync() { ... }
1.8. await の決まり事¶ • asyncなメソッドでのみ使用可 • finally, catch, lock内では使用不可 •
awaitableなメソッドにのみ付けれる
1.9. awaitableなメソッド?¶ • GetAwaiter() という名前のメソッド が定義された型 • そんな型を返すメソッド • Duck-Typing
1.10. awaitableなメソッド?¶ class Awatable { ... public Awaiter GetAwaiter() {
} ... }
1.11. Awaiter?¶ • INotifyCompletionインターフェースを実装 • IsCompletedプロパティ • GetResultメソッド • まぁ...そんな型
1.12. Awaiter?¶ struct Awaiter : INotifyCompletion { public bool IsCompleted
{ get; } public T GetResult() {} // from INotifyCompletion void OnCompleted(Action k) {} }
1.13. 標準では...¶ System.Threading.Tasks • Task • Task<T>
1.14. 標準では...¶ Windows.Foundation • IAsyncAction • IAsyncOperation<T> • IAsyncActionWithProgress •
IAsyncOperationWithProgress<T>
1.15. 同期化¶ • await後に元のスレッドに戻ってくる • SynchronizationContextが有効 • ConfigureAwait(false)でも無効化
1.16. 同期化¶ • WinRTでは • WinRTSynchronizationContext
1.17. 同期化¶ 注意 • 直接Taskをインスタンス化した場合 • 同期化されません • STA前提のメソッドは死ぬ
1.18. async / awaitの内側¶ • コンパイラの中の人が • 継続渡し、状態遷移機械などの • 黒魔術を駆使して
• 同期的な記述を非同期処理に変換
1.19. async / awaitの内側¶ ↓詳しくはココ http://blogs.msdn.com/b/ windowsappdev_ja/archive/ 2012/04/30/winrt-await.aspx
1.20. async / awaitでの苦労話¶ ココから本題
1.21. async / awaitでの苦労話¶ 1. 自前のTaskでawaitableなメソッド呼ぶ 結果 • 後続の実行前にTaskが完了する
1.22. async / awaitでの苦労話¶ await Task.Run(async () => { await
FooAsync(); // ↓実行されない return await BarAsync(); });
1.23. async / awaitでの苦労話¶ どうする? • 解決方法なし • 直接作ったTask中の使用はあきらめましょう
1.24. async / awaitでの苦労話¶ 1. Linqと相性が悪い • Linq内でawaitすると • 戻り値がIEnumerable<Task<TResult>>
1.25. async / awaitでの苦労話¶ var r = sources.Select(async (s) =>
{ return await BarAsync(s); });
1.26. async / awaitでの苦労話¶ • 値を取り出すために • foreachで回す必要があり
1.27. async / awaitでの苦労話¶ foreach (var task in results) {
var result = await task; }
1.28. async / awaitでの苦労話¶ • よく訓練されたLinq使い • foreachを嫌う • Linqのうまみ半減
1.29. async / awaitでの苦労話¶ どうする? • Linqとawaitの併用はあきらめましょう
1.30. async / awaitでの苦労話¶ 1. Task.Wait()で死ねる • 同期コンテキスト有効で • 非同期処理連鎖の内側で呼ぶと
• デッドロック
1.31. async / awaitでの苦労話¶ int Foo() { // ↓ 中でawaitするメソッド
var task = BarAsync(); // ココでお見合い task.Wait(); return task.Result; }
1.32. async / awaitでの苦労話¶ • 同期化のために • なかのawaitが呼出し元を待つから ↓詳しくはココミテ http://blogs.msdn.com/b/pfxteam/
archive/2012/04/12/10293249.aspx
1.33. async / awaitでの苦労話¶ どうする? • あきらめま(ry
1.34. async / awaitでの苦労話¶ 1. ならばと、GetAwaiter().GetResult()で無理矢理呼ぶ
1.35. async / awaitでの苦労話¶ public async void Foo() { var
task = BarAsync(); task.GetAwaiter().GetResult(); }
1.36. async / awaitでの苦労話¶ • 結果 • はい、デッドロック
1.37. async / awaitでの苦労話¶ どうする? • あ(ry
1.38. async / awaitでの苦労話¶ 1. Parallel.Foreachの中では使えない
1.39. async / awaitでの苦労話¶ Paralle.Foreach(list, async (x) => { await
Foo(x); }); • すべてのアクション完了まで待ってほしいのに... • Task.Run同様、投げっ放しジャーマン
1.40. async / awaitでの苦労話¶ どうする? • 気合いで非同期版作って下さい ↓ココミテ http://blogs.msdn.com/b/pfxteam/ archive/2012/03/04/10277325.aspx
1.41. async / awaitでの苦労話¶ 1. ユニットテストしづらい • NUnitはasync / await未対応
• 何も考えず走らせると • テストが実行されず終了(CLI版)
1.42. async / awaitでの苦労話¶ どうする?
1.43. async / awaitでの苦労話¶ CUI Runnerの場合 • 同期化されていないので • Taskk.Wait()
or GetAwaiter().GetResult()で待たせる
1.44. async / awaitでの苦労話¶ public void RunTest(Func<Task> inTest) { inTest.GetAwaiter().GetResult();
} [Test] public void _TestSomething() { RunTest(async () => { ... }); }
1.45. async / awaitでの苦労話¶ GUI Runnerの場合 • 自前の同期コンテキストを気合いで実装 • 割と安定してる
• けどグローバルな存在なので、ほかでこっそり使われると死ねる
1.46. WinRTのハマりどころ¶ • Windowsストアアプリ作成のためのAPIセット • 非同期処理を多用 • async / awaitの知識必須
1.47. Windowsストアアプリ¶ • Met(検閲により削除)... • とか言うと • MSの方から来た人に手招きされるかもなので注意
1.48. WinRTでの苦労話¶ 1. Windows.Storage APIの使用 スレッドまたいで使用するとSIBOU ArgumentException 範囲外です • (何が?)
COMException その他のエラー • (追跡不能)
1.49. WinRTでの苦労話¶ STAの制約っぽい • スレッドをまたがない • 再取得すると問題出ない
1.50. WinRTでの苦労話¶ 1. BackgroundTask • awaitすると • 戻ってくる前に完了状態になっちゃう
1.51. WinRTでの苦労話¶ どうする? • defferalを取得しておけば待ってくれる • GetDefferal() • 終わったらdefferalのComplete()呼ぶ
1.52. WinRTでの苦労話¶ 1. BackgroundTask スレッドの生成がアプリ本体とは異なる。 • メインスレッドがParallel#ForEachの中に入ってきた。
1.53. WinRTでの苦労話¶ 1. BackgroundTask • 中でTask.Wait()してしまっていたので • デッドロックした • /(^o^)\
1.54. まとめ¶ • C# 5.0で非同期処理が手軽に使えるようになった • けど...ハマりどころ多数 • まぁ、まるちすれっどですゆえ
1.55. まとめ¶ (・ワ・)