UnityにおけるAwaitAsyncを使った非同期実装について③
これまでTask、AsyncAwaitを使った非同期処理の実装、メインスレッド以外から特定の(メイン)スレッドにアクセスする方法についてみてきました。 今回は、複数の非同期に実行されるTaskをハンドリングする方法について説明します。今回もUnityに特化した情報はありません。
以下のコードがあったとします。
using System.Threading; using System.Threading.Tasks; using UnityEngine; public class AsyncSampleScene : MonoBehaviour { private async void Start() { await TestAsyncMethod1(); await TestAsyncMethod2(); await TestAsyncMethod3(); Debug.Log("All Compleated!"); } private async Task TestAsyncMethod1() { await Task.Run(() => { Debug.Log($"ID {Thread.CurrentThread.ManagedThreadId}, [Async] 1"); Thread.Sleep(1000); }); } private async Task TestAsyncMethod2() { await Task.Run(() => { Debug.Log($"ID {Thread.CurrentThread.ManagedThreadId}, [Async] 2"); Thread.Sleep(1000); }); } private async Task TestAsyncMethod3() { await Task.Run(() => { Debug.Log($"ID {Thread.CurrentThread.ManagedThreadId}, [Async] 3"); Thread.Sleep(1000); }); } }
TestAsyncMethod1()
が完了したらTestAsyncMethod2()
が実行され、TestAsyncMethod2()
が完了したらTestAsyncMethod3()
が実行され、
TestAsyncMethod3()
が完了したら最後にDebugログが出力されます。
図にすると以下のようになります。
しかし、TestAsyncMethod1()
、TestAsyncMethod2()
、TestAsyncMethod3()
に依存関係が特にない場合にはいちいちawait()
するのは無駄です。
この場合、このようになってほしいわけです。
それぞれのTaskをパラレルに実行し、全て完了したらDebugログを出力しています。
このような実装は以下のコードで実現できます。
using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using UnityEngine; public class AsyncSampleScene : MonoBehaviour { private async void Start() { List<Task> tasks = new List<Task>(); tasks.Add(TestAsyncMethod1()); tasks.Add(TestAsyncMethod2()); tasks.Add(TestAsyncMethod3()); await Task.WhenAll(tasks); Debug.Log("All Compleated!"); } private async Task TestAsyncMethod1() { await Task.Run(() => { Debug.Log($"ID {Thread.CurrentThread.ManagedThreadId}, [Async] 1"); Thread.Sleep(1000); }); } private async Task TestAsyncMethod2() { await Task.Run(() => { Debug.Log($"ID {Thread.CurrentThread.ManagedThreadId}, [Async] 2"); Thread.Sleep(1000); }); } private async Task TestAsyncMethod3() { await Task.Run(() => { Debug.Log($"ID {Thread.CurrentThread.ManagedThreadId}, [Async] 3"); Thread.Sleep(1000); }); } }
tasksというTaskのコレクションを生成し、各々のtaskをaddしていきます。最後にTask.WhenAll()
をawait
よって全てのコレクション内のTaskが完了したタイミングを取得することができます。