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
27
8.2k
DuckDB雑紹介
ktz
9
4.3k
Other Decks in Programming
See All in Programming
Beyond ORM
77web
3
380
Scalaから始めるOpenFeature入門 / Scalaわいわい勉強会 #4
arthur1
1
300
Асинхронность неизбежна: как мы проектировали сервис уведомлений
lamodatech
0
710
Effective Signals in Angular 19+: Rules and Helpers @ngbe2024
manfredsteyer
PRO
0
130
17年周年のWebアプリケーションにTanStack Queryを導入する / Implementing TanStack Query in a 17th Anniversary Web Application
saitolume
0
250
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
1.5k
htmxって知っていますか?次世代のHTML
hiro_ghap1
0
330
nekko cloudにおけるProxmox VE利用事例
irumaru
3
420
アクターシステムに頼らずEvent Sourcingする方法について
j5ik2o
4
230
テスト自動化失敗から再挑戦しチームにオーナーシップを委譲した話/STAC2024 macho
ma_cho29
1
1.3k
tidymodelsによるtidyな生存時間解析 / Japan.R2024
dropout009
1
770
Security_for_introducing_eBPF
kentatada
0
110
Featured
See All Featured
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
247
1.3M
Visualization
eitanlees
146
15k
The Cult of Friendly URLs
andyhume
78
6.1k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
66k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
28
4.4k
GraphQLとの向き合い方2022年版
quramy
44
13k
How to Think Like a Performance Engineer
csswizardry
22
1.2k
Building a Scalable Design System with Sketch
lauravandoore
460
33k
KATA
mclloyd
29
14k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
0
97
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. まとめ¶ (・ワ・)