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
430
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
21
6k
DuckDB雑紹介
ktz
9
4.1k
Other Decks in Programming
See All in Programming
Generative AI Use Cases JP (略称:GenU)奮闘記
hideg
0
150
Importmapを使ったJavaScriptの 読み込みとブラウザアドオンの影響
swamp09
4
1.2k
リリース8年目のサービスの1800個のERBファイルをViewComponentに移行した方法とその結果
katty0324
5
3.6k
2万ページのSSG運用における工夫と注意点 / Vue Fes Japan 2024
chinen
3
1.3k
GitHub Actionsのキャッシュと手を挙げることの大切さとそれに必要なこと
satoshi256kbyte
5
390
破壊せよ!データ破壊駆動で考えるドメインモデリング / data-destroy-driven
minodriven
16
4k
PHP でアセンブリ言語のように書く技術
memory1994
PRO
1
150
Piniaの現状と今後
waka292
5
1.4k
生成 AI を活用した toitta 切片分類機能の裏側 / Inside toitta's AI-Based Factoid Clustering
pokutuna
0
570
僕がつくった48個のWebサービス達
yusukebe
18
17k
弊社の「意識チョット低いアーキテクチャ」10選
texmeijin
5
23k
Streams APIとTCPフロー制御 / Web Streams API and TCP flow control
tasshi
1
290
Featured
See All Featured
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
Build The Right Thing And Hit Your Dates
maggiecrowley
32
2.4k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
13
1.9k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.6k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
3
370
Testing 201, or: Great Expectations
jmmastey
38
7k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
790
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
42
9.2k
Code Review Best Practice
trishagee
64
17k
Art, The Web, and Tiny UX
lynnandtonic
296
20k
Being A Developer After 40
akosma
86
590k
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. まとめ¶ (・ワ・)