MRが楽しい

MRやVRについて学習したことを書き残す

C#でCancellationTokenSourceを使って一定時間で非同期タスクのキャンセルを行う

本日は C# の小ネタ枠です。
C# で CancellationTokenSource を使って一定時間で非同期タスクのキャンセルを行う方法についてです。

CancellationTokenSource.CancelAfter

CancellationTokenSource.CancelAfter を使って Cancel の発生タイミングを時間指定で設定できます。
learn.microsoft.com

var cancelTokenSource = new CancellationTokenSource();
cancelTokenSource.CancelAfter(2000);

サンプルシーン

以下の SemaphoreSlim を使ってスレッド制御を行ったサンプルシーンでキャンセル処理を実装してみます。
bluebirdofoz.hatenablog.com

スレッド待機が2秒以上続く場合、待機をキャンセルするように以下の通り実装を変更しました。
・SemaphoreSlimCancelTest1.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class SemaphoreSlimCancelTest1 : MonoBehaviour
{ 
    // 同時に1つまでのタスクを許容し、かつ、タスクの数を後から追加できないようにする
    private SemaphoreSlim _semaphoreSlim = new (1,1);
    
    public async void ButtonEvent()
    {
        // 2秒以上待機する場合は待機をキャンセルする
        var cancelTokenSource = new CancellationTokenSource();
        cancelTokenSource.CancelAfter(2000);

        try
        {
            // スレッドをブロックする(非同期で行いたい場合は WaitAsync() を使用する)
            await _semaphoreSlim.WaitAsync(cancelTokenSource.Token);
            // 1秒ごとに1~3のカウントダウンをログに出力する
            for (int count = 1; count <= 3; count++)
            {
                Debug.Log(count);
                await Task.Delay(1000);
            }

            // スレッドを解放する
            _semaphoreSlim.Release();
        }
        catch (OperationCanceledException)
        {
            Debug.Log("待機キャンセルされました");
        }
        finally
        {
            cancelTokenSource.Dispose();
        }
    }
}

シーンを再生して動作を確認します。
ボタンを連打すると、以下の通り2回目の待機が実行前にキャンセルされました。