개요
- Unity는 Thread를 생성하여 사용할 수 있다.
- 다만 이 영역에서는 MonoBehaviour가 동작하지 않는다.
- 따라서 멀티 쓰레딩(multi-threading) 환경에서는, Unity의 ManagedThread를 체크할 필요가 있다.
방법
- 아래 예제에서는 ManagedThread에서 동작하기 원하는 Action을 RunOnUiThread에 넣는다.
- EditorApplication.Update를 사용하여 Main Application의 업데이트를 감지한다.
- 이 방식을 사용하면, StartCoroutine 같은 명령을 외부 Thread에서 입력할 수 있다.
- 실제 실행은 ManagedThread에서 된다.
코드
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
public class FileBasketSyncContext
{
private static SynchronizationContext context;
private static TaskScheduler taskScheduler;
private static int managedThreadId;
private static Queue<Action> runInUpdate = new Queue<Action>();
public static bool isUiThread => managedThreadId == Thread.CurrentThread.ManagedThreadId;
public void Awake()
{
context = SynchronizationContext.Current;
managedThreadId = Thread.CurrentThread.ManagedThreadId;
taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
EditorApplication.update += OnEditorApplicationUpdate;
}
public static SynchronizationContext GetContext()
{
return context;
}
public static void RunOnUiThread(Action runnable)
{
if (managedThreadId == Thread.CurrentThread.ManagedThreadId)
{
runnable();
}
else
{
lock (runInUpdate)
{
runInUpdate.Enqueue(runnable);
}
}
}
private static void OnEditorApplicationUpdate()
{
while (runInUpdate.Count > 0)
{
Action runnable = null;
lock (runInUpdate)
{
if (runInUpdate.Count > 0)
{
runnable = runInUpdate.Dequeue();
}
}
// runnable이 null이 아니라면 실행
runnable?.Invoke();
}
}
}