Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
C# async/await 勉強会
Search
Hiroki Kamiyoshikawa
May 05, 2025
Programming
27
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
C# async/await 勉強会
C# の非同期処理における async/await の構造や動作原理についての解説。
(2023/1/27 社内勉強会用)
Hiroki Kamiyoshikawa
May 05, 2025
More Decks by Hiroki Kamiyoshikawa
See All by Hiroki Kamiyoshikawa
コンパイラを作ろう
ikorin24
0
51
NAND から全加算器まで (CPU の仕組み超入門)
ikorin24
0
450
Other Decks in Programming
See All in Programming
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
3.8k
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
220
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
390
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
270
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
210
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
2
350
AmebaブログはKMPから卒業します
kmars0605
0
200
Featured
See All Featured
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
From π to Pie charts
rasagy
1
400
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
Leo the Paperboy
mayatellez
10
2.4k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
820
KATA
mclloyd
PRO
35
16k
The Cost Of JavaScript in 2023
addyosmani
55
10k
ラッコキーワード サービス紹介資料
rakko
1
5.4M
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
580
Transcript
C# async/await 勉強会 2021/11/08 作成者 ikorin
async/await の登場 var foo = new Foo(); foo.Completed += result
=> { Debug.Log($" 答えは {result} です"); }; foo.Do(); public class Foo { public event Action<int> Completed; public void Do() { new Thread(() => { // とても重い計算処理 var result = 1 + 1; Completed?.Invoke(result); }).Start(); } } var foo = new Foo(); var result = await foo.DoAsync(); Debug.Log($" 答えは {result} です"); public class Foo { public async UniTask<int> DoAsync() { await UniTask.SwitchToThreadPool(); // とても重い計算処理 return 1 + 1; } } 完了イベントによるコールバック async/await による実装 多段に非同期処理を書くと可読性が悪い 非同期処理内の例外のハンドリングが困難 await を並べるだけで多段に非同期実行可能 非同期処理内の例外も呼び出し元まで伝播する
非同期処理とバックグラウンド処理 バックグラウンドスレッド実行のために非同期処理を簡潔に書くための構文が必要 GUI アプリケーションでは重い処理をバックグラウンドスレッドで実行したい Task, async/await 構文 async/await 登場から UniTask
登場まで UniTask Unity バックグラウンド実行することを主目的として async/await と Task を導入したため、メインスレッド内のみで非同期処理をする API は Task には用意されていない ・スレッドの概念と非同期処理の概念を分離している ・Unity で使える各種便利機能 Unity 以外ではバックグラウンド処理以外で非同期処理を扱う必要がほぼないため、 決して Task と async/await の作成者が 非同期とスレッドの概念を混同しているわけではない。
Time Frame n n+1 n+2 n+a EarlyUpdate Update LateUpdate object1
object2 object3 object1 object2 object3 object1 object2 object3 CPU の処理の流れ プログラマが実装したい処理の流れ CPU の処理の流れとプログラマが実装したい処理の流れの乖離 Unity Player Loop 両者の流れが違うため、実装が複雑になる
Time Frame n n+1 n+2 n+a EarlyUpdate Update LateUpdate object1
object2 object3 object1 object2 object3 object1 object2 object3 'await' = その位置で CPU の処理の流れをジャンプする ( かもしれない) 'async' = そのメソッドの中でジャンプする ( かもしれない) ことを示すマーク await UniTask.DelayFrame(a) await UniTask.Yield(PlayerLoopTiming.EarlyUpdate) await UniTask.CompletedTask ( ジャンプしない) async と await の意味 await によってプログラマにとって都合のいい処理の流れを作れる Unity Player Loop
Time Frame n n+1 n+2 n+a EarlyUpdate Update LateUpdate object1
object2 object3 await はスレッド間をジャンプすることもできる Background Thread Main Thread await UniTask.SwitchToThreadPool() await UniTask.SwitchToMainThread(PlayerLoopTiming.LateUpdate) object1 object2 object3 await によるスレッド間移動 Unity Player Loop
同期コンテキスト (SynchronizationContext) await UniTask.SwitchToThreadPool() await UniTask.Yield() await UniTask.CompletedTask ( ジャンプしない)
await Task.Run(action) ( メインスレッドで開始) action Main Thread Thread A await Task.Run(action) ( 非メインスレッドで開始) action Thread A Thread B await Task.Run(action).ConfigureAwait(false) ( メインスレッドで開始) action Main Thread Thread A Main Thread Thread A await UniTask.DelayFrame(a) メインスレッドの同期コンテキストの作用で 暗黙的にメインスレッドに戻る action Thread A Thread B await Task.Run(action).ConfigureAwait(false) ( 非メインスレッドで開始) 明示的に同期コンテキストをつかまないよう指示 (.ConfigureAwait(false)) 非メインスレッド (Thread A) には 同期コンテキストは存在しないため Thread B で継続 同期コンテキストは存在しないため ConfigureAwait の指定は true でも false でも 戻らない UniTask Task UniTask は同期コンテキストをキャプチャしない。 終了時のスレッドでそのまま継続処理を実行。 Task は同期コンテキストがあればキャプチャする。 キャプチャすると元のスレッドに戻り継続処理を実行。
async メソッドの戻り値 await Hoge(true) DoSomething() Main Thread Thread A async
UniTask Hoge(bool xxx) { if (xxx) { return; } await UniTask.SwitchToThreadPool(); DoSomething(); return; } Main Thread await Hoge(false) await Hoge(true) DoSomething() Main Thread Thread A async Task Hoge(bool xxx) { if (xxx) { return; } await UniTask.SwitchToThreadPool(); DoSomething(); return; } Main Thread await Hoge(false) async Task はメインスレッドで await すると 暗黙的にメインスレッドに戻る ( 同期コンテキストをキャプチャする) async UniTask は終了時のスレッドで継続する ( 同期コンテキストをキャプチャしない) async メソッドはコンパイラによって async を使わない形に変形される。async は糖衣構文。 その戻り値の UniTask, Task はコンパイラが自動生成する。 UniTask Task
await によるジャンプはデリゲートのキュー UniTask Task Main Thread Thread A async UniTask
Piyo() { await UniTask.SwitchToThreadPool(); DoSomething(); return; } await Piyo() Piyo() DoSomething() UniTask.SwitchToThreadPool() Thread A のキューに DoSomething を入れる キューから DoSomething が とりだされて実行 Piyo() の戻り値は UniTask であるため メインスレッドの同期コンテキストを キャプチャしていない。 そのまま継続処理を実行 Main Thread Thread A Piyo() DoSomething() UniTask.SwitchToThreadPool() UniTask と同じ Piyo() の戻り値は Task であるため メインスレッドの同期コンテキストを キャプチャしている。 同期コンテキストのキューに 継続処理をポスト UniTask と同じ 同期コンテキストのキューから 継続処理を取り出して実行 await Piyo() async Task Piyo() { await UniTask.SwitchToThreadPool(); DoSomething(); return; }
async void はなぜ非推奨か Main Thread Thread A Main Thread Thread
A 例外発生 catch Main Thread Thread A await による待機呼び出し await による呼び出しは どこで例外が発生しても await を追跡して遡る Main Thread Thread A Main Thread Thread A 例外発生 catch async void による待機なし呼び出し async void は await できないため ジャンプした処理を追跡できない Main Thread Thread A 未キャッチ例外が漏れる async void は開始した処理の 終了を検知できないため 継続処理を書けない 同期的な例外はキャッチ可能 async void を await できないのは何が困るのか async void を書いてもいい条件 ・未キャッチ例外が確実に漏れないこと ・開始した非同期処理の終了を検知する必要がないこと (fire and forget)