はなちるのマイノート

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

【UniTask】SuppressCancellationThrowを使ってキャンセルを返り値として取り出す

はじめに

今回はSuppressCancellationThrowについて触れていきたいと思います。

SuppressCancellationThrowの使い場面は簡単に言うと、タスクがキャンセルされたかどうかを返り値として取り出す場合です。

// 通常
try
{
    await NormalTask(ctx.Token);
}
catch (OperationCanceledException)
{
    // キャンセルされている場合
}

// SuppressCancellationThrowを使った場合
var isCancelled = await SuppressCancellationThrowTask(ctx.Token); 

SuppressCancellationThrowの使い方

SuppressCancellationThrowUniTaskの場合とUniTask<T>の場合の2つあります。

// UniTaskの場合
public UniTask<bool> SuppressCancellationThrow();

// UniTask<T>の場合
public UniTask<(bool IsCanceled, T Result)> SuppressCancellationThrow();

冒頭でも述べた通り、OperationCanceledExceptionを投げるのではなくboolの値としてキャンセルされたかどうかを判断することができます。


簡単なコードを見ながら使い方をみていきましょう。

public class SuppressCancellationThrowTest : MonoBehaviour
{
    private async void Start()
    {
        var ctx = new CancellationTokenSource();
        ctx.Cancel();
            
        try
        {
            await NormalCancelCase(ctx.Token);
        }
        catch (OperationCanceledException)
        {
            // 実行される
            Debug.Log("task is canceled.");
        }
        
        var isCancelled = await SuppressCancellationThrowCase(ctx.Token); 
            
        // true
        Debug.Log(isCancelled);
            
        var (isCancelled2, result) = await SuppressCancellationThrowCase2(ctx.Token);
            
        // true
        Debug.Log(isCancelled2);
        Debug.Log(result == null);
    }
    
    private async UniTask NormalCancelCase(CancellationToken token)
    {
        await UniTask.WaitUntil(() => false, cancellationToken: token);
    }

    private async UniTask<bool> SuppressCancellationThrowCase(CancellationToken token)
    {
        // public UniTask<bool> SuppressCancellationThrow();
        return await UniTask.WaitUntil(() => false, cancellationToken: token).SuppressCancellationThrow();
    }
        
    private async UniTask<(bool, string)> SuppressCancellationThrowCase2(CancellationToken token)
    {
        // public UniTask<(bool IsCanceled, T Result)> SuppressCancellationThrow();
        return await UniTask.WaitUntil(() => false, cancellationToken: token).ContinueWith(() => "ハロー").SuppressCancellationThrow();
    }
}


UniTaskUniTask<T>という構造体の中にメソッドとして定義されているので,上のようにメソッドチェーンのように書けます。

さいごに

C# でない言語だと,未定義であったりエラーであったりキャンセルであったり?を返り値として取り出せるものもあるらしいです。

私自身こちらを使われているのはみたことはありますが、使ったことがほぼないのでうまく使いこないしたいところです。

ではまた。