はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#, Unity】ValueTask.AsTaskを利用してValueTask<TResult>からTask<TResult>に変換をする

はじめに

今回はValueTask.AsTaskメソッドについて紹介をします。

learn.microsoft.com

説明

AsTaskを実行すると以下の挙動になります。

この ValueTask でラップされる Task オブジェクト (存在する場合)、または、結果を表す新しい Task オブジェクト。

ValueTask.AsTask メソッド (System.Threading.Tasks) | Microsoft Learn

相変わらず公式ドキュメントはカタコトですが、

  • Taskのインスタンスが存在する(非同期処理)場合はそのままTaskを返す
  • Taskのインスタンスが存在しない(同期処理)場合は結果を格納した新しいTaskを生成して返す

ということだと思います。

ValueTaskの良さを潰しているといったらそうな気もしますが、Taskに変換する必要があるなら仕方がないでしょう。

private async void Start()
{
    // ValueTask<TResult>
    // ValueTaskはWhenAllやWhenAnyが適応できない
    ValueTask<bool> valueTask = SampleAsync();
        
    // 同期処理のため既に終わっている
    Debug.Log(valueTask.IsCompleted);               // true
    Debug.Log(valueTask.IsCompletedSuccessfully);   // true
    Debug.Log(valueTask.Result);                    // true
        
    bool result = await valueTask;
        
    Debug.Log(valueTask.IsCompleted);               // true
    Debug.Log(valueTask.IsCompletedSuccessfully);   // true
    Debug.Log(valueTask.Result);                    // true
    Debug.Log(result);                              // true

    // AsTask
    Task<bool> task = SampleAsync().AsTask();
        
    // 同期処理のため既に終わっている
    // Task<TResult>が生成されていた場合はそれを返し、存在しない場合は新しいTask<TResult>を生成する
    Debug.Log(task.IsCompleted);                    // true
    Debug.Log(task.IsCompletedSuccessfully);        // true
    Debug.Log(task.Result);                         // true

    bool result2 = await task;

    Debug.Log(task.IsCompleted);                    // true
    Debug.Log(task.IsCompletedSuccessfully);        // true
    Debug.Log(task.Result);                         // true
    Debug.Log(result2);
}

private async ValueTask<bool> SampleAsync()
    => true;

private async ValueTask<bool> Sample2Async()
    => true;

ちなみにですが、UnityにはValueTaskに対してWhenAllWhenAnyを適応できるようにしたValueTaskSupplementというライブラリがあったりします。

github.com