MRが楽しい

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

UnityでUniTaskを使ってメインスレッドとバックグラウンドの処理を切り替える

本日はUniTaskの小ネタ枠です。
UnityでUniTaskを使ってメインスレッドとバックグラウンドの処理を切り替える方法についてです。

SwitchToThreadPoolとSwitchToMainThread

UniTaskのSwitchToThreadPoolとSwitchToMainThreadは非同期タスクの実行スレッドを切り替えるためのユーティリティです。
SwitchToThreadPoolでバックグラウンド処理に切り替わり、SwitchToMainThreadでメインスレッド処理に切り替わります。

public async UniTask LoadDataAsync()
{
    // メインスレッド上
    Debug.Log("処理開始");

    await UniTask.SwitchToThreadPool();
    string data = LoadHeavyData(); // メインスレッドをブロックしない

    await UniTask.SwitchToMainThread();
    Debug.Log($"データ読み込み完了: {data}"); // Unity APIを安全に使用
}

サンプルスクリプト

SwitchToThreadPoolとSwitchToMainThreadメソッドを使って処理の途中でバックグラウンドに処理を切り替えるサンプルスクリプトを作成しました。
・MainThreadTest3.cs

using UnityEngine;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;

/// <summary>
/// メインスレッドを判定するサンプルクラス
/// </summary>
public class MainThreadTest3 : MonoBehaviour
{
    // 現在のメインスレッドのID
    private int mainThreadId;

    // 現在のメインスレッドのコンテキスト
    private System.Threading.SynchronizationContext mainThreadContext;

    void Start()
    {
        // メインスレッドのIDを取得
        mainThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

        // メインスレッドのコンテキストを取得
        mainThreadContext = System.Threading.SynchronizationContext.Current;

        Debug.Log("Main Thread ID: " + mainThreadId);
        Debug.Log("Main Thread Context: " + (mainThreadContext != null ? "Available" : "Not Available"));
    }

    [ContextMenu("Switch Method Test")]
    async Task SwitchMethodTest()
    {
        // メインスレッドでの処理
        // メインスレッドで実行されているかどうかを判定
        Debug.Log("Start Message : " + (IsMainThreadByThreadId(System.Threading.Thread.CurrentThread.ManagedThreadId) ? "Main Thread" : "Not Main Thread"));

        // バックグラウンドスレッドに切り替え
        await UniTask.SwitchToThreadPool();

        // バックグラウンドスレッドでの処理
        // バックグラウンドで実行されているかどうかを判定
        Debug.Log("Switch Message : " + (IsMainThreadByThreadId(System.Threading.Thread.CurrentThread.ManagedThreadId) ? "Main Thread" : "Not Main Thread"));

        // メインスレッドに戻る
        await UniTask.SwitchToMainThread();

        // メインスレッドで実行されているかどうかを判定
        Debug.Log("End Message : " + (IsMainThreadByThreadId(System.Threading.Thread.CurrentThread.ManagedThreadId) ? "Main Thread" : "Not Main Thread"));
    }

    /// <summary>
    /// スレッドIDを使ってメインスレッドかどうかを判定するメソッド
    /// </summary>
    /// <param name="checkThreadId"></param>
    /// <returns></returns>
    private bool IsMainThreadByThreadId(int checkThreadId)
    {
        // 現在のスレッドがメインスレッドかどうかを判定
        return checkThreadId == mainThreadId;
    }
}

以下の通り、コードの途中で実行スレッドが切り替わり、メインスレッド処理 -> バックグラウンド処理 -> メインスレッド処理の順でログが表示されます。