Awaitable を使用した非同期プログラミングの概要
Understand the key features of Unity's Awaitable and how it compares to both .NET Task and iterator-based coroutines.
読み終わるまでの所要時間 11 分最終更新 1ヶ月前
Awaitableasyncawait- Unity コルーチン: 、
NextFrameAsync、WaitForSecondsAsync、EndOfFrameAsyncFixedUpdateAsync - バックグラウンドスレッド または メインスレッド への切り替え
- を継承するすべての型
AsyncOperation - Unity Learn:イベント
- 非同期 GPU リードバック
以下のように、 クラスを 演算子と の戻り値の型の両方とともに独自のコードで使用できます。
Awaitableawaitasyncasync Awaitable<List<Achievement>> GetAchievementsAsync(){ var apiResult = await SomeMethodReturningATask(); // or any await-compatible type List<Achievement> achievements = JsonConvert.DeserializeObject<List<Achievement>>(apiResult); return achievements;}async Awaitable ShowAchievementsView(){ ShowLoadingOverlay(); List<Achievement> achievements = await GetAchievementsAsync(); HideLoadingOverlay(); ShowAchivementsList(achievements);}
Awaitable と .NET Task の比較
AwaitableTaskAwaitableTask最も重要な制限は、 インスタンスが割り当てを制限するためにプールされることです。以下の例を考えてみてください。
Awaitableclass SomeMonoBehaviorWithAwaitable : MonoBehavior{ public async void Start() { while(true) { // do some work on each frame await Awaitable.NextFrameAsync(); } }}
この例の の各インスタンスは、プーリングを行わないと、フレームごとに オブジェクトを割り当て、ガベージコレクターのワークロード を増加させ、パフォーマンスを低下させます。これを軽減するために、Unity は待機後に オブジェクトを内部 プールに返します。
MonoBehaviorAwaitableAwaitableAwaitable重要: インスタンスのプーリングは、1 つの インスタンスを複数回 することは決して安全ではないことを意味します。これを行うと、例外やデッドロックなどの未定義の動作につながる可能性があります。
AwaitableAwaitableawaitAwaitable と .NET ValueTask の比較
.NET は、 と同じ主なメリットと制限をいくつか提供します。 の推奨される一般的な使用法は、ほとんどの場合に同期的に完了すると予想される非同期ワークロードです。詳細については、Understanding the Whys, Whats, and Whens of ValueTask を参照してください。
ValueTask<TResult>AwaitableValueTaskAwaitable、Task、ValueTask の要約
以下の表は、Unity の クラスと .NET および の機能比較をまとめたものです。
AwaitableTaskValueTask機能 |
|
|
|
|---|---|---|---|
| 必要な割り当て | 多い。 | 必要に応じて。 プーリングを使用して最適化できます。 | 必要最小限。 |
| 安全に複数回待機可能 | 可。 | 不可。 | 不可。 カスタムの |
| 継続の非同期実行 | 可。 同期コンテキストをデフォルトで使用します。それ以外の場合は | 可。 待機中のタスクが同期的に完了するケースに最適化されています。非同期的に完了する場合、継続動作は | 不可。 継続は、完了がトリガーされると同期的に実行されます。つまり、コードは、完了がトリガーされたのと同じフレーム内ですぐに再開されます。詳細については、Awaitable の完了と継続 を参照してください。 |
| コードによって完了をトリガー可能 | 可。 | 一般的なユースケース (ほとんどの場合に同期的に完了するタスク) には適用されません。 | 可。 |
| 値を返すことが可能 | 可。 | 可。 | 可。 |
| 可。 | 不可。 | 不可。 カスタムの |
| Unity スレッドと更新ループに対応した実行スケジュール | 不可。 | 不可。 | 可。 |
Task または ValueTask よりも Awaitable を使用する場合
API の選択は非同期コードのパフォーマンスプロファイルによって異なりますが、一般的には以下のように選択します。
-
は、複数回待機する必要がある場合や、複数のコンシューマーから同時に待機する必要がある場合の唯一の選択肢です。
Task -
は、ほとんどの場合に同期的に完了する高スループットの非同期コードがある場合に適しています。
ValueTask -
は、以下のような場合に適しています。
Awaitable- メソッドを複数回待機する必要がなく、ほとんどが非同期的に完了する場合。
- 非同期タスクに、メインスレッド、Update ループ、FixedUpdate ループといった Unity 固有の概念のビルトインサポートが必要な場合。
Awaitable とイテレーターベースのコルーチンの比較
AwaitableWaitForFixedUpdateただし、多くの コルーチンを同時に実行すると、パフォーマンス上のメリットが低下します。例えば、前述のコード例のような MonoBehaviour は、 ループで を待機しますが、大規模なプロジェクト内のすべてのゲームオブジェクトにアタッチされると、パフォーマンスの問題が発生する可能性があります。
AwaitablewhileAwaitable.NextFrameAsync