質問: /*async*/ () => //■■■■■■■■■■■■■■■■■■■■here■■■■■■■■■■■■■■■■■■■■ { while (true) { Debug.Log("loop!"); //await Task.Delay(1000); //■■■■■■■■■■■■■■■■■■■■here■■■■■■■■■■■■■■■■■■■■ _token.ThrowIfCancellationRequested(); } }; return action; } } ``` ### 補足情報(FW/ツールのバージョンなど) C# .Net4.6 Unity 2017.1.0f3 新規シーンで、Emptyオブジェクトに上記のスクリプトをコンポーネントとして 登録していただければ動作します。 Editor上での動作を想定しており、Editor実行時にConsole画面に"loop!"という 文字列が一気にwhile文で表示されSpaceキーを押すと止まります。 UnityというよりはC#の書き方の問題だと思います。 私のC#のTask周りの知識が怪しく分かりにくいサンプルで申し訳ありません。 おそらく根本的な箇所を勘違いしてしまっていると思いますのでご指摘いただけるとありがたいです。 よろしくお願い致します。
回答: こんにちは。 この問題の直接的な原因は、temp関数が`Action`で宣言されていることです。 tempに非同期処理(コメントアウトを外した状態)を入れるということは、戻り値のない非同期処理、即ち、`async void`(待機不可能な非同期処理)を宣言していることと同意です。 コメントアウトを外した状態では、「キャンセルが発行されたあと、1秒以内に例外が出るが、その例外が出るのを"待たずに"キャンセル処理が先に進む」という状況になっています。 さらには、その例外はcatch可能なコンテキストでthrowされていないので、根本的にcatchできない状態になっています。 最低限の変更で意図した動作を実現するには、temp関数の`Action`を`Func`型に変更します。 Task.Runは真っ当な非同期メソッドを受け取った場合は適切に待機処理を受け渡してくれます。