【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう

Unity Technologies Japan K.K.
Unity Technologies Japan K.K.Unity Technologies Japan K.K.
さては非同期だなオメー!
async/await完全に理解しよう
ユニティ・テクノロジーズ・ジャパン
名雪 通
2018/05/07 - 09
名雪 通
asyncのほう。
エンジニア
安原 祐二
awaitのほう。
エンジニア
#unitetokyo2018
#完全に理解した
2018年5月
Unity 2018.1 リリース
.NET 4.xがExperimental→Stableに!
C# 4.0→6.0
参考: C# 5.0の新機能
• async/await
• 呼び出し元情報属性
参考: C# 6.0の新機能
• 読み取り専用の自動プロパティ
• 自動プロパティの初期化子
• 式形式の関数メンバー
• using static
• null条件演算子
• 文字列補間
• 例外フィルター
• nameof式
• catchブロックとfinallyブロックでのawait
• インデックス初期化子
• コレクション初期化子の拡張メソッド
• オーバーロード解決の改善
async/await
async/awaitとは何か
async(= asynchronous = 非同期)
awaitを使うメソッドにつける必要があるキーワード
await(= 待つ)
非同期(async)メソッドを呼び出し、
その完了まで実行を中断するキーワード
ここまででのasync/await理解率: 10%
ここで問題です
このコードの開始→終了まで何秒かかるでしょうか
static void AsyncTest() {
// 開始
Console.WriteLine(DateTime.Now);
Thread.Sleep(5000);
// 終了
Console.WriteLine(DateTime.Now);
}
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
普通に5秒
次の問題
このコードは開始→終了まで何秒かかるでしょうか
static void AsyncTest() {
// 開始
Console.WriteLine(DateTime.Now);
AsyncMethod();
// 終了
Console.WriteLine(DateTime.Now);
}
static async void AsyncMethod() {
Thread.Sleep(5000);
}
やっぱり5秒
別にasyncをつけただけで非同期になるわけではない
次はawaitの問題
このコードは開始→終了まで何秒かかるでしょうか
static void AsyncTest() {
// 開始
Console.WriteLine(DateTime.Now);
Task.Delay(5000);
// 終了
Console.WriteLine(DateTime.Now);
}
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
なんと0秒
次の問題
このコードは開始→終了まで何秒かかるでしょうか
static async void AsyncTest() {
// 開始
Console.WriteLine(DateTime.Now);
await Task.Delay(5000);
// 終了
Console.WriteLine(DateTime.Now);
}
5秒になった!
async/awaitは
「処理を非同期に行うための仕組み」ではなく、
「非同期の処理を待つための仕組み」である
理解率: 50%
では、どのように
その「非同期の処理を待つための仕組み」を
実現しているのか?
逆コンパイルしてみよう
さっきのコード
static async void AsyncTest() {
// 開始
Console.WriteLine(DateTime.Now);
await Task.Delay(5000);
// 終了
Console.WriteLine(DateTime.Now);
}
逆コンパイルした結果
    private static void AsyncTest() {
        <AsyncTest>d__1 <AsyncTest>d__ = new <AsyncTest>d__1();
        <AsyncTest>d__.<>t__builder = AsyncVoidMethodBuilder.Create();
        <AsyncTest>d__.<>1__state = -1;
        AsyncVoidMethodBuilder <>t__builder = <AsyncTest>d__.<>t__builder;
        <>t__builder.Start(ref <AsyncTest>d__);
    }
インナークラスも生成されている
    private sealed class <AsyncTest>d__1 : IAsyncStateMachine {
        public int <>1__state;
        public AsyncVoidMethodBuilder <>t__builder;
        private TaskAwaiter <>u__1;
        private void MoveNext() {
            int num = <>1__state;
            try {
                TaskAwaiter awaiter;
                if (num != 0) {
                    Console.WriteLine(DateTime.Now);
                    awaiter = Task.Delay(5000).GetAwaiter();
                    if (!awaiter.get_IsCompleted()) {
                        num = (<>1__state = 0);
                        <>u__1 = awaiter;
                        <AsyncTest>d__1 <AsyncTest>d__ = this;
                        <>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter,
<AsyncTest>d__1>(ref awaiter, ref <AsyncTest>d__);
                        return;
                    }
                } else {
                    awaiter = <>u__1;
                    <>u__1 = default(TaskAwaiter);
                    num = (<>1__state = -1);
                }
                awaiter.GetResult();
                Console.WriteLine(DateTime.Now);
            }
            catch (Exception exception)
            {
                <>1__state = -2;
                <>t__builder.SetException(exception);
                return;
            }
            <>1__state = -2;
            <>t__builder.SetResult();
        }
    }
わかりやすく書き直してみる
元の関数
    private static void AsyncTest() {
        var stateMachine = new AsyncTestStateMachine();
        stateMachine.builder = AsyncVoidMethodBuilder.Create();
        stateMachine.state = -1;
        stateMachine.builder.Start(ref stateMachine);
    }
static async void AsyncTest() {
Console.WriteLine(DateTime.Now); // 開始
await Task.Delay(5000);
Console.WriteLine(DateTime.Now); // 終了
}
    private sealed struct AsyncTestStateMachine : IAsyncStateMachine {
        public int state;
        public AsyncVoidMethodBuilder builder;
        private TaskAwaiter taskAwaiter;
        private void MoveNext() {
            int num = state;
            try {
                TaskAwaiter awaiter;
                if (num != 0) {
                    Console.WriteLine(DateTime.Now);
                    awaiter = Task.Delay(5000).GetAwaiter();
                    if (!awaiter.IsCompleted) {
                        num = state = 0;
                        taskAwaiter = awaiter;
                        AsyncTestStateMachine stateMachine = this;
                        builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref
awaiter, ref stateMachine);
                        return;
                    }
                } else {
                    awaiter = taskAwaiter;
                    taskAwaiter = default(TaskAwaiter);
                    num = state = -1;
                }
                awaiter.GetResult();
                Console.WriteLine(DateTime.Now);
            }
            catch (Exception exception)
            {
                state = -2;
                builder.SetException(exception);
                return;
            }
            state = -2;
            builder.SetResult();
        }
    }
インナークラス
    private sealed struct AsyncTestStateMachine : IAsyncStateMachine {
        public int state;
        public AsyncVoidMethodBuilder builder;
        private TaskAwaiter taskAwaiter;
        private void MoveNext() {
            int num = state;
            try {
                TaskAwaiter awaiter;
                if (num != 0) {
                    Console.WriteLine(DateTime.Now);
                    awaiter = Task.Delay(5000).GetAwaiter();
                    if (!awaiter.IsCompleted) {
                        num = state = 0;
                        taskAwaiter = awaiter;
                        AsyncTestStateMachine stateMachine = this;
                        builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref
awaiter, ref stateMachine);
                        return;
                    }
                } else {
                    awaiter = taskAwaiter;
                    taskAwaiter = default(TaskAwaiter);
                    num = state = -1;
                }
                awaiter.GetResult();
                Console.WriteLine(DateTime.Now);
            }
            catch (Exception exception)
            {
                state = -2;
                builder.SetException(exception);
                return;
            }
            state = -2;
            builder.SetResult();
        }
    }
インナークラスのMoveNext
private void MoveNext() {
    private sealed struct AsyncTestStateMachine : IAsyncStateMachine {
        public int state;
        public AsyncVoidMethodBuilder builder;
        private TaskAwaiter taskAwaiter;
        private void MoveNext() {
            int num = state;
            try {
                TaskAwaiter awaiter;
                if (num != 0) {
                    Console.WriteLine(DateTime.Now);
                    awaiter = Task.Delay(5000).GetAwaiter();
                    if (!awaiter.IsCompleted) {
                        num = state = 0;
                        taskAwaiter = awaiter;
                        AsyncTestStateMachine stateMachine = this;
                        builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref
awaiter, ref stateMachine);
                        return;
                    }
                } else {
                    awaiter = taskAwaiter;
                    taskAwaiter = default(TaskAwaiter);
                    num = state = -1;
                }
                awaiter.GetResult();
                Console.WriteLine(DateTime.Now);
            }
            catch (Exception exception)
            {
                state = -2;
                builder.SetException(exception);
                return;
            }
            state = -2;
            builder.SetResult();
        }
    }
インナークラス
TaskAwaiter awaiter;
if (num != 0) {
    Console.WriteLine(DateTime.Now);
    awaiter = Task.Delay(5000).GetAwaiter();
Console.WriteLine(DateTime.Now);
関数を抜けてる!
    private sealed struct AsyncTestStateMachine : IAsyncStateMachine {
        public int state;
        public AsyncVoidMethodBuilder builder;
        private TaskAwaiter taskAwaiter;
        private void MoveNext() {
            int num = state;
            try {
                TaskAwaiter awaiter;
                if (num != 0) {
                    Console.WriteLine(DateTime.Now);
                    awaiter = Task.Delay(5000).GetAwaiter();
                    if (!awaiter.IsCompleted) {
                        num = state = 0;
                        taskAwaiter = awaiter;
                        AsyncTestStateMachine stateMachine = this;
                        builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref
awaiter, ref stateMachine);
                        return;
                    }
                } else {
                    awaiter = taskAwaiter;
                    taskAwaiter = default(TaskAwaiter);
                    num = state = -1;
                }
                awaiter.GetResult();
                Console.WriteLine(DateTime.Now);
            }
            catch (Exception exception)
            {
                state = -2;
                builder.SetException(exception);
                return;
            }
            state = -2;
            builder.SetResult();
        }
    }
 return;
問題です
Task.Delayの前後の実行スレッドは?
static void Main(string[] args) {
AsyncTest();
Console.ReadLine();
}
static async void AsyncTest() {
// 前
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await Task.Delay(5000);
// 後
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
違う
同じコードをUnityで実行すると?
    async void Start () {
        // 前
        Debug.Log(Thread.CurrentThread.ManagedThreadId);
        await Task.Delay(5000);
        // 後
        Debug.Log(Thread.CurrentThread.ManagedThreadId);
    }
同じ!
SynchronizationContextが
await後のコードを実行するスレッドを決める
CLIアプリケーションには
SynchronizationContextが存在しないため
自動的にスレッドプール上で実行される
UnityにはUnityの
SynchronizationContextの実装がある
参考: https://github.com/Unity-Technologies/UnityCsReference/blob/
83cceb769a97e24025616acc7503e9c21891f0f1/Runtime/Export/
UnitySynchronizationContext.cs
もともとUnityには
非同期処理のための仕組みがあります
コルーチン
• C# 2.0の反復子(yield)を利用した継続処理の仕組み
• 様々なタイミングを待つことができる(Unity側の仕組みによる)
• フレームの終わり
• FixedUpdate
• 指定した秒数後(の最初のフレーム)
• その他非同期処理(AsyncOperation)
• 戻り値を返しにくい
コルーチンの例
    IEnumerator Coroutine() {
        // 前
        Debug.Log(Thread.CurrentThread.ManagedThreadId);
        yield return new WaitForSeconds(0.5f);
        // 後
        Debug.Log(Thread.CurrentThread.ManagedThreadId);
    }
逆コンパイルしてみよう
    private IEnumerator Coroutine() {
        return new <Coroutine>c__Iterator1();
    }
    private sealed class <Coroutine>c__Iterator1 : IEnumerator, IDisposable, IEnumerator<object> {
        internal object $current;
        internal bool $disposing;
        internal int $PC;
        object IEnumerator<object>.Current {
            [DebuggerHidden]
            get
            {
                return $current;
            }
        }
        object IEnumerator.Current {
            [DebuggerHidden]
            get
            {
                return $current;
            }
        }
        public <Coroutine>c__Iterator1() {
        }
        public bool MoveNext() {
            //IL_003c: Unknown result type (might be due to invalid IL or missing references)
            //IL_0041: Expected O, but got Unknown
            uint num = (uint)$PC;
            $PC = -1;
            switch (num) {
            case 0u:
                Debug.Log((object)Thread.CurrentThread.ManagedThreadId);
                $current = (object)new WaitForSeconds(0.5f);
                if (!$disposing) {
                    $PC = 1;
                }
                return true;
            case 1u:
                Debug.Log((object)Thread.CurrentThread.ManagedThreadId);
                $PC = -1;
                break;
            }
            return false;
        }
        public void Dispose() {
            $disposing = true;
            $PC = -1;
        }
        public void Reset() {
            throw new NotSupportedException();
        }
    }
C# Job System
• 2018.1の新機能
• クラスが使えない
• Burstコンパイラーによる最適化の恩恵を受けられる
• 処理はUnityのワーカースレッドで実行される
awaitできるのはTaskだけではない
TaskをawaitするのがTaskAwaiter
Awaiterを作ればTaskでなくてもawaitできる  
awaitしたいクラスにGetAwaiter拡張メソッドを実装する
public static class AsyncOperationAwaitable {
    public static Awaiter GetAwaiter(this AsyncOperation asyncOperation) {
        return new Awaiter(asyncOperation);
    }
    public class AsyncOperationAwaiter : INotifyCompletion {
    private AsyncOperation asyncOperation;
     private System.Action continuation;
    public AsyncOperationAwaiter(AsyncOperation asyncOperation) {
    this.asyncOperation = asyncOperation;
     CoroutineDispatcher.Get().DispatchCoroutine(WrappedCoroutine());
    }
    public bool IsCompleted {
    get { return asyncOperation.isDone; }
    }
    public void OnCompleted(System.Action continuation) {
    this.continuation = continuation;
    }
     public void GetResult() {
     }
    public IEnumerator WrappedCoroutine() {
    yield return asyncOperation;
     continuation();
    }
    }
}
• サンプルです。そのまま使わないでください。
サンプル: HTTPリクエストして
レスポンスのJSONをパースする
コルーチンで書く
    IEnumerator Coroutine() {
        UnityWebRequest request = UnityWebRequest.Get("https://api.etherscan.io/api?
module=proxy&action=eth_getBlockByNumber&tag=0x517df3&boolean=true&apikey=YourApiKeyToken");
        yield return request.SendWebRequest();
        var text = request.downloadHandler.text;
        var data = (JObject)JsonConvert.DeserializeObject(text);
        var result = (JObject)data["result"];
        var transactions = (JArray)result["transactions"];
        Debug.Log(transactions.Count);
    }
非同期
同期
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
Task + async/awaitを使って書く
    async Task Async() {
        UnityWebRequest request = UnityWebRequest.Get("https://api.etherscan.io/api?
module=proxy&action=eth_getBlockByNumber&tag=0x517df3&boolean=true&apikey=YourApiKeyToken");
        await request.SendWebRequest();
        var text = request.downloadHandler.text;
        await Task.Run(() => {
            var data = (JObject)JsonConvert.DeserializeObject(text);
            var result = (JObject)data["result"];
            var transactions = (JArray)result["transactions"];
            Debug.Log(JsonConvert.DeserializeObject(text));
        });
    }
非同期
非同期
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
JSONパース処理(45ms)分が
非同期(メインスレッド外)で行われるように
実はUnityのプロファイラーには
Profiler.BeginThreadProfilingしたスレッドしか
表示されない
スレッドプールのスレッドごとに
Profiler.BeginThreadProfilingを呼ぶ
TaskSchedulerを作ればよい
参考: https://github.com/tnayuki/Unity-AsyncAwait/blob/master/Assets/
UnityTaskScheduler.cs
※ 参照実装です。そのまま使わないでください。
まとめ
• async/awaitは非同期処理を待つための仕組み
• 仕組みがわからない時は逆コンパイルしよう(ライセンスには気をつけよう)
• コルーチン/C# Job Systemと使い分けよう
• Task.Runに回した処理は通常はUnityのプロファイラーから見えないので注意
「async/await完全に理解した」
Thank you!
ご静聴ありがとうございました
1 de 68

Recomendados

async/await のしくみ por
async/await のしくみasync/await のしくみ
async/await のしくみ信之 岩永
19.8K vistas41 diapositivas
【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~ por
【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~
【Unite Tokyo 2019】今すぐ現場で覚えておきたい最適化技法 ~「ゲシュタルト・オーディン」開発における最適化事例~UnityTechnologiesJapan002
9.8K vistas42 diapositivas
Unity 2018-2019を見据えたDeNAのUnity開発のこれから [DeNA TechCon 2019] por
Unity 2018-2019を見据えたDeNAのUnity開発のこれから [DeNA TechCon 2019]Unity 2018-2019を見据えたDeNAのUnity開発のこれから [DeNA TechCon 2019]
Unity 2018-2019を見据えたDeNAのUnity開発のこれから [DeNA TechCon 2019]DeNA
23.2K vistas85 diapositivas
Unityでパフォーマンスの良いUIを作る為のTips por
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnity Technologies Japan K.K.
81.5K vistas87 diapositivas
コールバックと戦う話 por
コールバックと戦う話コールバックと戦う話
コールバックと戦う話torisoup
3K vistas59 diapositivas
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術 por
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術Unity Technologies Japan K.K.
28.6K vistas112 diapositivas

Más contenido relacionado

La actualidad más candente

「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像 por
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像エピック・ゲームズ・ジャパン Epic Games Japan
8.3K vistas132 diapositivas
Deep Dive async/await in Unity with UniTask(UniRx.Async) por
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Yoshifumi Kawai
105.7K vistas68 diapositivas
Riderはいいぞ! por
Riderはいいぞ!Riderはいいぞ!
Riderはいいぞ!UnityTechnologiesJapan002
14.4K vistas145 diapositivas
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説 por
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説Unity Technologies Japan K.K.
42.9K vistas60 diapositivas
オブジェクト指向できていますか? por
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
237.5K vistas129 diapositivas
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~ por
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~エピック・ゲームズ・ジャパン Epic Games Japan
35.1K vistas153 diapositivas

La actualidad más candente(20)

Deep Dive async/await in Unity with UniTask(UniRx.Async) por Yoshifumi Kawai
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Yoshifumi Kawai105.7K vistas
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説 por Unity Technologies Japan K.K.
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
オブジェクト指向できていますか? por Moriharu Ohzu
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu237.5K vistas
MagicOnion入門 por torisoup
MagicOnion入門MagicOnion入門
MagicOnion入門
torisoup10.4K vistas
Unityではじめるオープンワールド制作 エンジニア編 por Unity Technologies Japan K.K.
Unityではじめるオープンワールド制作 エンジニア編Unityではじめるオープンワールド制作 エンジニア編
Unityではじめるオープンワールド制作 エンジニア編
Unityでオニオンアーキテクチャ por torisoup
UnityでオニオンアーキテクチャUnityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャ
torisoup10K vistas
ゲーム開発者のための C++11/C++14 por Ryo Suzuki
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
Ryo Suzuki103.6K vistas
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~ por UnityTechnologiesJapan002
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
UniTask入門 por torisoup
UniTask入門UniTask入門
UniTask入門
torisoup14.2K vistas
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう por UnityTechnologiesJapan002
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
オンラインゲームの仕組みと工夫 por Yuta Imai
オンラインゲームの仕組みと工夫オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫
Yuta Imai869.9K vistas
UnrealBuildTool勉強会まとめ por Shun Sasaki
UnrealBuildTool勉強会まとめUnrealBuildTool勉強会まとめ
UnrealBuildTool勉強会まとめ
Shun Sasaki13K vistas
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について por com044
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動についてUE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
com04423.2K vistas
なぜなにリアルタイムレンダリング por Satoshi Kodaira
なぜなにリアルタイムレンダリングなぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリング
Satoshi Kodaira90.5K vistas
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」 por U-dai Yokoyama
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
U-dai Yokoyama18K vistas

Similar a 【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう

NoSQL and JavaScript 2013-02-09 por
NoSQL and JavaScript 2013-02-09NoSQL and JavaScript 2013-02-09
NoSQL and JavaScript 2013-02-09WakandaJA
1.1K vistas24 diapositivas
Azure で Serverless 初心者向けタッチ&トライ por
Azure で Serverless 初心者向けタッチ&トライAzure で Serverless 初心者向けタッチ&トライ
Azure で Serverless 初心者向けタッチ&トライMasanobu Sato
2.4K vistas38 diapositivas
ゼロから始めたE2Eテスト por
ゼロから始めたE2Eテストゼロから始めたE2Eテスト
ゼロから始めたE2Eテストushiboy
3.6K vistas44 diapositivas
T93 com入門 por
T93 com入門T93 com入門
T93 com入門伸男 伊藤
2.3K vistas48 diapositivas
20141129-dotNet2015 por
20141129-dotNet201520141129-dotNet2015
20141129-dotNet2015Takayoshi Tanaka
13.2K vistas39 diapositivas
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~ por
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~normalian
10.4K vistas42 diapositivas

Similar a 【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう(20)

NoSQL and JavaScript 2013-02-09 por WakandaJA
NoSQL and JavaScript 2013-02-09NoSQL and JavaScript 2013-02-09
NoSQL and JavaScript 2013-02-09
WakandaJA1.1K vistas
Azure で Serverless 初心者向けタッチ&トライ por Masanobu Sato
Azure で Serverless 初心者向けタッチ&トライAzure で Serverless 初心者向けタッチ&トライ
Azure で Serverless 初心者向けタッチ&トライ
Masanobu Sato2.4K vistas
ゼロから始めたE2Eテスト por ushiboy
ゼロから始めたE2Eテストゼロから始めたE2Eテスト
ゼロから始めたE2Eテスト
ushiboy3.6K vistas
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~ por normalian
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
normalian10.4K vistas
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE) por Tusyoshi Matsuzaki
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE).NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)
Tusyoshi Matsuzaki4.9K vistas
React Native GUIDE por dcubeio
React Native GUIDEReact Native GUIDE
React Native GUIDE
dcubeio1.3K vistas
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」 por de:code 2017
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
de:code 20171.4K vistas
Swift 2.0 大域関数の行方から #swift2symposium por Tomohiro Kumagai
Swift 2.0 大域関数の行方から #swift2symposiumSwift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposium
Tomohiro Kumagai12.7K vistas
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall por なおき きしだ
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fallこれからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
なおき きしだ15.5K vistas
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題 por Makoto Setoh
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
Makoto Setoh2.3K vistas
T69 c++cli ネイティブライブラリラッピング入門 por 伸男 伊藤
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
伸男 伊藤5.2K vistas
TypeScript 言語処理系ことはじめ por Yu Nobuoka
TypeScript 言語処理系ことはじめTypeScript 言語処理系ことはじめ
TypeScript 言語処理系ことはじめ
Yu Nobuoka3.3K vistas
Let's build a simple app with .net 6 asp.net core web api, react, and elasti... por Shotaro Suzuki
Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Shotaro Suzuki368 vistas
Apache Torqueについて por tako pons
Apache TorqueについてApache Torqueについて
Apache Torqueについて
tako pons2.2K vistas
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8 por y_taka_23
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_2321.2K vistas
ソーシャルアプリ勉強会(第一回資料)配布用 por Yatabe Terumasa
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
Yatabe Terumasa1.5K vistas

Más de Unity Technologies Japan K.K.

建築革命、更に更に進化!便利さ向上【Unity Reflect ver 3.0 】 por
建築革命、更に更に進化!便利さ向上【Unity Reflect ver 3.0 】建築革命、更に更に進化!便利さ向上【Unity Reflect ver 3.0 】
建築革命、更に更に進化!便利さ向上【Unity Reflect ver 3.0 】Unity Technologies Japan K.K.
2K vistas47 diapositivas
UnityのクラッシュをBacktraceでデバッグしよう! por
UnityのクラッシュをBacktraceでデバッグしよう!UnityのクラッシュをBacktraceでデバッグしよう!
UnityのクラッシュをBacktraceでデバッグしよう!Unity Technologies Japan K.K.
1.7K vistas32 diapositivas
Unityで始めるバーチャルプロダクション por
Unityで始めるバーチャルプロダクションUnityで始めるバーチャルプロダクション
Unityで始めるバーチャルプロダクションUnity Technologies Japan K.K.
3.8K vistas20 diapositivas
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう por
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしようビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしようUnity Technologies Japan K.K.
2.7K vistas50 diapositivas
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション por
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーションビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - UnityステーションUnity Technologies Japan K.K.
2K vistas49 diapositivas
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう por
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそうビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそうUnity Technologies Japan K.K.
5.8K vistas63 diapositivas

Más de Unity Technologies Japan K.K.(20)

ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう por Unity Technologies Japan K.K.
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしようビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション por Unity Technologies Japan K.K.
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーションビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう por Unity Technologies Japan K.K.
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそうビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】 por Unity Technologies Japan K.K.
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
Unity教える先生方注目!ティーチャートレーニングデイを体験しよう por Unity Technologies Japan K.K.
Unity教える先生方注目!ティーチャートレーニングデイを体験しようUnity教える先生方注目!ティーチャートレーニングデイを体験しよう
Unity教える先生方注目!ティーチャートレーニングデイを体験しよう
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】 por Unity Technologies Japan K.K.
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】

Último

Windows 11 information that can be used at the development site por
Windows 11 information that can be used at the development siteWindows 11 information that can be used at the development site
Windows 11 information that can be used at the development siteAtomu Hidaka
90 vistas41 diapositivas
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料) por
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)NTT DATA Technology & Innovation
32 vistas38 diapositivas
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20... por
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...NTT DATA Technology & Innovation
158 vistas42 diapositivas
Keycloakの全体像: 基本概念、ユースケース、そして最新の開発動向 por
Keycloakの全体像: 基本概念、ユースケース、そして最新の開発動向Keycloakの全体像: 基本概念、ユースケース、そして最新の開発動向
Keycloakの全体像: 基本概念、ユースケース、そして最新の開発動向Hitachi, Ltd. OSS Solution Center.
101 vistas26 diapositivas
The Things Stack説明資料 by The Things Industries por
The Things Stack説明資料 by The Things IndustriesThe Things Stack説明資料 by The Things Industries
The Things Stack説明資料 by The Things IndustriesCRI Japan, Inc.
78 vistas29 diapositivas

Último(12)

Windows 11 information that can be used at the development site por Atomu Hidaka
Windows 11 information that can be used at the development siteWindows 11 information that can be used at the development site
Windows 11 information that can be used at the development site
Atomu Hidaka90 vistas
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料) por NTT DATA Technology & Innovation
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20... por NTT DATA Technology & Innovation
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
The Things Stack説明資料 by The Things Industries por CRI Japan, Inc.
The Things Stack説明資料 by The Things IndustriesThe Things Stack説明資料 by The Things Industries
The Things Stack説明資料 by The Things Industries
CRI Japan, Inc.78 vistas
PCCC23:富士通株式会社 テーマ1「次世代高性能・省電力プロセッサ『FUJITSU-MONAKA』」 por PC Cluster Consortium
PCCC23:富士通株式会社 テーマ1「次世代高性能・省電力プロセッサ『FUJITSU-MONAKA』」PCCC23:富士通株式会社 テーマ1「次世代高性能・省電力プロセッサ『FUJITSU-MONAKA』」
PCCC23:富士通株式会社 テーマ1「次世代高性能・省電力プロセッサ『FUJITSU-MONAKA』」
PCCC23:東京大学情報基盤センター 「Society5.0の実現を目指す『計算・データ・学習』の融合による革新的スーパーコンピューティング」 por PC Cluster Consortium
PCCC23:東京大学情報基盤センター 「Society5.0の実現を目指す『計算・データ・学習』の融合による革新的スーパーコンピューティング」PCCC23:東京大学情報基盤センター 「Society5.0の実現を目指す『計算・データ・学習』の融合による革新的スーパーコンピューティング」
PCCC23:東京大学情報基盤センター 「Society5.0の実現を目指す『計算・データ・学習』の融合による革新的スーパーコンピューティング」
光コラボは契約してはいけない por Takuya Matsunaga
光コラボは契約してはいけない光コラボは契約してはいけない
光コラボは契約してはいけない
Takuya Matsunaga27 vistas
SNMPセキュリティ超入門 por mkoda
SNMPセキュリティ超入門SNMPセキュリティ超入門
SNMPセキュリティ超入門
mkoda479 vistas
SSH応用編_20231129.pdf por icebreaker4
SSH応用編_20231129.pdfSSH応用編_20231129.pdf
SSH応用編_20231129.pdf
icebreaker4405 vistas

【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう

  • 9. 参考: C# 5.0の新機能 • async/await • 呼び出し元情報属性
  • 10. 参考: C# 6.0の新機能 • 読み取り専用の自動プロパティ • 自動プロパティの初期化子 • 式形式の関数メンバー • using static • null条件演算子 • 文字列補間 • 例外フィルター • nameof式 • catchブロックとfinallyブロックでのawait • インデックス初期化子 • コレクション初期化子の拡張メソッド • オーバーロード解決の改善
  • 13. async(= asynchronous = 非同期) awaitを使うメソッドにつける必要があるキーワード
  • 17. このコードの開始→終了まで何秒かかるでしょうか static void AsyncTest() { // 開始 Console.WriteLine(DateTime.Now); Thread.Sleep(5000); // 終了 Console.WriteLine(DateTime.Now); }
  • 21. このコードは開始→終了まで何秒かかるでしょうか static void AsyncTest() { // 開始 Console.WriteLine(DateTime.Now); AsyncMethod(); // 終了 Console.WriteLine(DateTime.Now); } static async void AsyncMethod() { Thread.Sleep(5000); }
  • 25. このコードは開始→終了まで何秒かかるでしょうか static void AsyncTest() { // 開始 Console.WriteLine(DateTime.Now); Task.Delay(5000); // 終了 Console.WriteLine(DateTime.Now); }
  • 29. このコードは開始→終了まで何秒かかるでしょうか static async void AsyncTest() { // 開始 Console.WriteLine(DateTime.Now); await Task.Delay(5000); // 終了 Console.WriteLine(DateTime.Now); }
  • 34. さっきのコード static async void AsyncTest() { // 開始 Console.WriteLine(DateTime.Now); await Task.Delay(5000); // 終了 Console.WriteLine(DateTime.Now); }
  • 35. 逆コンパイルした結果     private static void AsyncTest() {         <AsyncTest>d__1 <AsyncTest>d__ = new <AsyncTest>d__1();         <AsyncTest>d__.<>t__builder = AsyncVoidMethodBuilder.Create();         <AsyncTest>d__.<>1__state = -1;         AsyncVoidMethodBuilder <>t__builder = <AsyncTest>d__.<>t__builder;         <>t__builder.Start(ref <AsyncTest>d__);     }
  • 36. インナークラスも生成されている     private sealed class <AsyncTest>d__1 : IAsyncStateMachine {         public int <>1__state;         public AsyncVoidMethodBuilder <>t__builder;         private TaskAwaiter <>u__1;         private void MoveNext() {             int num = <>1__state;             try {                 TaskAwaiter awaiter;                 if (num != 0) {                     Console.WriteLine(DateTime.Now);                     awaiter = Task.Delay(5000).GetAwaiter();                     if (!awaiter.get_IsCompleted()) {                         num = (<>1__state = 0);                         <>u__1 = awaiter;                         <AsyncTest>d__1 <AsyncTest>d__ = this;                         <>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, <AsyncTest>d__1>(ref awaiter, ref <AsyncTest>d__);                         return;                     }                 } else {                     awaiter = <>u__1;                     <>u__1 = default(TaskAwaiter);                     num = (<>1__state = -1);                 }                 awaiter.GetResult();                 Console.WriteLine(DateTime.Now);             }             catch (Exception exception)             {                 <>1__state = -2;                 <>t__builder.SetException(exception);                 return;             }             <>1__state = -2;             <>t__builder.SetResult();         }     }
  • 38. 元の関数     private static void AsyncTest() {         var stateMachine = new AsyncTestStateMachine();         stateMachine.builder = AsyncVoidMethodBuilder.Create();         stateMachine.state = -1;         stateMachine.builder.Start(ref stateMachine);     } static async void AsyncTest() { Console.WriteLine(DateTime.Now); // 開始 await Task.Delay(5000); Console.WriteLine(DateTime.Now); // 終了 }
  • 39.     private sealed struct AsyncTestStateMachine : IAsyncStateMachine {         public int state;         public AsyncVoidMethodBuilder builder;         private TaskAwaiter taskAwaiter;         private void MoveNext() {             int num = state;             try {                 TaskAwaiter awaiter;                 if (num != 0) {                     Console.WriteLine(DateTime.Now);                     awaiter = Task.Delay(5000).GetAwaiter();                     if (!awaiter.IsCompleted) {                         num = state = 0;                         taskAwaiter = awaiter;                         AsyncTestStateMachine stateMachine = this;                         builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref awaiter, ref stateMachine);                         return;                     }                 } else {                     awaiter = taskAwaiter;                     taskAwaiter = default(TaskAwaiter);                     num = state = -1;                 }                 awaiter.GetResult();                 Console.WriteLine(DateTime.Now);             }             catch (Exception exception)             {                 state = -2;                 builder.SetException(exception);                 return;             }             state = -2;             builder.SetResult();         }     } インナークラス
  • 40.     private sealed struct AsyncTestStateMachine : IAsyncStateMachine {         public int state;         public AsyncVoidMethodBuilder builder;         private TaskAwaiter taskAwaiter;         private void MoveNext() {             int num = state;             try {                 TaskAwaiter awaiter;                 if (num != 0) {                     Console.WriteLine(DateTime.Now);                     awaiter = Task.Delay(5000).GetAwaiter();                     if (!awaiter.IsCompleted) {                         num = state = 0;                         taskAwaiter = awaiter;                         AsyncTestStateMachine stateMachine = this;                         builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref awaiter, ref stateMachine);                         return;                     }                 } else {                     awaiter = taskAwaiter;                     taskAwaiter = default(TaskAwaiter);                     num = state = -1;                 }                 awaiter.GetResult();                 Console.WriteLine(DateTime.Now);             }             catch (Exception exception)             {                 state = -2;                 builder.SetException(exception);                 return;             }             state = -2;             builder.SetResult();         }     } インナークラスのMoveNext private void MoveNext() {
  • 41.     private sealed struct AsyncTestStateMachine : IAsyncStateMachine {         public int state;         public AsyncVoidMethodBuilder builder;         private TaskAwaiter taskAwaiter;         private void MoveNext() {             int num = state;             try {                 TaskAwaiter awaiter;                 if (num != 0) {                     Console.WriteLine(DateTime.Now);                     awaiter = Task.Delay(5000).GetAwaiter();                     if (!awaiter.IsCompleted) {                         num = state = 0;                         taskAwaiter = awaiter;                         AsyncTestStateMachine stateMachine = this;                         builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref awaiter, ref stateMachine);                         return;                     }                 } else {                     awaiter = taskAwaiter;                     taskAwaiter = default(TaskAwaiter);                     num = state = -1;                 }                 awaiter.GetResult();                 Console.WriteLine(DateTime.Now);             }             catch (Exception exception)             {                 state = -2;                 builder.SetException(exception);                 return;             }             state = -2;             builder.SetResult();         }     } インナークラス TaskAwaiter awaiter; if (num != 0) {     Console.WriteLine(DateTime.Now);     awaiter = Task.Delay(5000).GetAwaiter(); Console.WriteLine(DateTime.Now);
  • 42. 関数を抜けてる!     private sealed struct AsyncTestStateMachine : IAsyncStateMachine {         public int state;         public AsyncVoidMethodBuilder builder;         private TaskAwaiter taskAwaiter;         private void MoveNext() {             int num = state;             try {                 TaskAwaiter awaiter;                 if (num != 0) {                     Console.WriteLine(DateTime.Now);                     awaiter = Task.Delay(5000).GetAwaiter();                     if (!awaiter.IsCompleted) {                         num = state = 0;                         taskAwaiter = awaiter;                         AsyncTestStateMachine stateMachine = this;                         builder.AwaitUnsafeOnCompleted<TaskAwaiter, AsyncTestStateMachine>(ref awaiter, ref stateMachine);                         return;                     }                 } else {                     awaiter = taskAwaiter;                     taskAwaiter = default(TaskAwaiter);                     num = state = -1;                 }                 awaiter.GetResult();                 Console.WriteLine(DateTime.Now);             }             catch (Exception exception)             {                 state = -2;                 builder.SetException(exception);                 return;             }             state = -2;             builder.SetResult();         }     }  return;
  • 44. Task.Delayの前後の実行スレッドは? static void Main(string[] args) { AsyncTest(); Console.ReadLine(); } static async void AsyncTest() { // 前 Console.WriteLine(Thread.CurrentThread.ManagedThreadId); await Task.Delay(5000); // 後 Console.WriteLine(Thread.CurrentThread.ManagedThreadId); }
  • 46. 同じコードをUnityで実行すると?     async void Start () {         // 前         Debug.Log(Thread.CurrentThread.ManagedThreadId);         await Task.Delay(5000);         // 後         Debug.Log(Thread.CurrentThread.ManagedThreadId);     }
  • 51. コルーチン • C# 2.0の反復子(yield)を利用した継続処理の仕組み • 様々なタイミングを待つことができる(Unity側の仕組みによる) • フレームの終わり • FixedUpdate • 指定した秒数後(の最初のフレーム) • その他非同期処理(AsyncOperation) • 戻り値を返しにくい
  • 52. コルーチンの例     IEnumerator Coroutine() {         // 前         Debug.Log(Thread.CurrentThread.ManagedThreadId);         yield return new WaitForSeconds(0.5f);         // 後         Debug.Log(Thread.CurrentThread.ManagedThreadId);     }
  • 53. 逆コンパイルしてみよう     private IEnumerator Coroutine() {         return new <Coroutine>c__Iterator1();     }     private sealed class <Coroutine>c__Iterator1 : IEnumerator, IDisposable, IEnumerator<object> {         internal object $current;         internal bool $disposing;         internal int $PC;         object IEnumerator<object>.Current {             [DebuggerHidden]             get             {                 return $current;             }         }         object IEnumerator.Current {             [DebuggerHidden]             get             {                 return $current;             }         }         public <Coroutine>c__Iterator1() {         }         public bool MoveNext() {             //IL_003c: Unknown result type (might be due to invalid IL or missing references)             //IL_0041: Expected O, but got Unknown             uint num = (uint)$PC;             $PC = -1;             switch (num) {             case 0u:                 Debug.Log((object)Thread.CurrentThread.ManagedThreadId);                 $current = (object)new WaitForSeconds(0.5f);                 if (!$disposing) {                     $PC = 1;                 }                 return true;             case 1u:                 Debug.Log((object)Thread.CurrentThread.ManagedThreadId);                 $PC = -1;                 break;             }             return false;         }         public void Dispose() {             $disposing = true;             $PC = -1;         }         public void Reset() {             throw new NotSupportedException();         }     }
  • 54. C# Job System • 2018.1の新機能 • クラスが使えない • Burstコンパイラーによる最適化の恩恵を受けられる • 処理はUnityのワーカースレッドで実行される
  • 57. awaitしたいクラスにGetAwaiter拡張メソッドを実装する public static class AsyncOperationAwaitable {     public static Awaiter GetAwaiter(this AsyncOperation asyncOperation) {         return new Awaiter(asyncOperation);     }     public class AsyncOperationAwaiter : INotifyCompletion {     private AsyncOperation asyncOperation;      private System.Action continuation;     public AsyncOperationAwaiter(AsyncOperation asyncOperation) {     this.asyncOperation = asyncOperation;      CoroutineDispatcher.Get().DispatchCoroutine(WrappedCoroutine());     }     public bool IsCompleted {     get { return asyncOperation.isDone; }     }     public void OnCompleted(System.Action continuation) {     this.continuation = continuation;     }      public void GetResult() {      }     public IEnumerator WrappedCoroutine() {     yield return asyncOperation;      continuation();     }     } } • サンプルです。そのまま使わないでください。
  • 59. コルーチンで書く     IEnumerator Coroutine() {         UnityWebRequest request = UnityWebRequest.Get("https://api.etherscan.io/api? module=proxy&action=eth_getBlockByNumber&tag=0x517df3&boolean=true&apikey=YourApiKeyToken");         yield return request.SendWebRequest();         var text = request.downloadHandler.text;         var data = (JObject)JsonConvert.DeserializeObject(text);         var result = (JObject)data["result"];         var transactions = (JArray)result["transactions"];         Debug.Log(transactions.Count);     } 非同期 同期
  • 61. Task + async/awaitを使って書く     async Task Async() {         UnityWebRequest request = UnityWebRequest.Get("https://api.etherscan.io/api? module=proxy&action=eth_getBlockByNumber&tag=0x517df3&boolean=true&apikey=YourApiKeyToken");         await request.SendWebRequest();         var text = request.downloadHandler.text;         await Task.Run(() => {             var data = (JObject)JsonConvert.DeserializeObject(text);             var result = (JObject)data["result"];             var transactions = (JArray)result["transactions"];             Debug.Log(JsonConvert.DeserializeObject(text));         });     } 非同期 非同期
  • 66. まとめ • async/awaitは非同期処理を待つための仕組み • 仕組みがわからない時は逆コンパイルしよう(ライセンスには気をつけよう) • コルーチン/C# Job Systemと使い分けよう • Task.Runに回した処理は通常はUnityのプロファイラーから見えないので注意