本日はUnityの小ネタ枠です。
Unityで実行中のスクリプトでメインスレッドか判定する方法についてです。
メインスレッドの判定方法
スクリプトでメインスレッドを判定する場合、スレッドIDを控えておく方法かSynchronizationContextを参照する方法が一般的です。
private static int mainThreadId; void Start() { // Startは必ずメインスレッド上で呼ばれる mainThreadId = Thread.CurrentThread.ManagedThreadId; } public static bool IsMainThread() { return Thread.CurrentThread.ManagedThreadId == mainThreadId; }
private static SynchronizationContext mainThreadContext; void Start() { // Startは必ずメインスレッド上で呼ばれる mainThreadContext = SynchronizationContext.Current; } public static bool IsMainThread() { return SynchronizationContext.Current == mainThreadContext; }
サンプルスクリプト
2つの方法でメインスレッドを判定する以下のサンプルスクリプトを作成しました。
・MainThreadTest.cs
using UnityEngine; /// <summary> /// メインスレッドを判定するサンプルクラス /// </summary> public class MainThreadTest : 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("Check Method Test")] void CheckMethodTest() { // 実行したスレッドのIDを取得して、メインスレッドと比較 int currentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; bool isMainThreadById = IsMainThreadByThreadId(currentThreadId); Debug.Log("Result : " + (isMainThreadById ? "Main Thread" : "Not Main Thread") + " (Thread ID: " + currentThreadId + ")"); // 実行したスレッドのコンテキストを取得して、メインスレッドのコンテキストと比較 System.Threading.SynchronizationContext currentContext = System.Threading.SynchronizationContext.Current; bool isMainThreadByContext = IsMainThreadByContext(currentContext); Debug.Log("Result : " + (isMainThreadByContext ? "Main Thread" : "Not Main Thread") + " (Context: " + (currentContext != null ? "Available" : "Not Available") + ")"); // バックグラウンドスレッドで確認 new System.Threading.Thread(() => { // 実行したスレッドのIDを取得して、メインスレッドと比較 int currentBackgroundThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; bool isMainThreadById = IsMainThreadByThreadId(currentBackgroundThreadId); Debug.Log("Result : " + (isMainThreadById ? "Main Thread" : "Not Main Thread") + " (Thread ID: " + currentBackgroundThreadId + ")"); // 実行したスレッドのコンテキストを取得して、メインスレッドのコンテキストと比較 System.Threading.SynchronizationContext currentBackgroundContext = System.Threading.SynchronizationContext.Current; bool isMainThreadByContext = IsMainThreadByContext(currentBackgroundContext); Debug.Log("Result : " + (isMainThreadByContext ? "Main Thread" : "Not Main Thread") + " (Context: " + (currentBackgroundContext != null ? "Available" : "Not Available") + ")"); }).Start(); } /// <summary> /// スレッドIDを使ってメインスレッドかどうかを判定するメソッド /// </summary> /// <param name="checkThreadId"></param> /// <returns></returns> private bool IsMainThreadByThreadId(int checkThreadId) { if (checkThreadId == mainThreadId) { Debug.Log("This is the main thread."); } else { Debug.Log("This is NOT the main thread."); } // 現在のスレッドがメインスレッドかどうかを判定 return checkThreadId == mainThreadId; } /// <summary> /// スレッドコンテキストを使ってメインスレッドかどうかを判定するメソッド /// </summary> /// <param name="checkContext"></param> /// <returns></returns> private bool IsMainThreadByContext(System.Threading.SynchronizationContext checkContext) { if (checkContext == mainThreadContext) { Debug.Log("This is the main thread context."); } else { Debug.Log("This is NOT the main thread context."); } // 現在のコンテキストがメインスレッドのコンテキストかどうかを判定 return checkContext == mainThreadContext; } }
コンテクストメニューからテスト関数を実行すると、メインスレッドの判定が行えました。
