Unity3D 子线程访问主线程方法
1.在初始化时的主线程中调用一次Loom.Initialize();
2.在任意场景任意线程均可调用Loom.QueueOnMainThread()来完成主线程的操作
3.Loom类参考
public class Loom : MonoBehaviour
{
public const int maxThreads = 8;
private static int numThreads;
private static bool initialized;
private static Loom current;
private readonly List<Action> actions = new List<Action>();
private readonly List<DelayedQueueItem> delayed = new List<DelayedQueueItem>();
private readonly List<DelayedQueueItem> currentDelayed = new List<DelayedQueueItem>();
private readonly List<Action> currentActions = new List<Action>();
public static Loom Current
{
get
{
Initialize();
return current;
}
}
void Start()
{
}
void Update()
{
lock (actions)
{
currentActions.Clear();
currentActions.AddRange(actions);
actions.Clear();
}
foreach (var a in currentActions)
{
a();
}
lock (delayed)
{
currentDelayed.Clear();
currentDelayed.AddRange(delayed.Where(d => d.time <= Time.time));
foreach (var item in currentDelayed)
delayed.Remove(item);
}
foreach (var delayed in currentDelayed)
{
delayed.action();
}
}
/// <summary>
/// 初始化
/// </summary>
public static void Initialize()
{
if (!initialized)
{
if (!Application.isPlaying)
return;
initialized = true;
GameObject g = new GameObject("Loom");
// 永不销毁
DontDestroyOnLoad(g);
current = g.AddComponent<Loom>();
}
}
public static void QueueOnMainThread(Action action)
{
QueueOnMainThread(action, 0f);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
if (Current != null)
{
lock (Current.delayed)
{
Current.delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
}
else
{
if (Current != null)
{
lock (Current.actions)
{
Current.actions.Add(action);
}
}
}
}
public static Thread RunAsync(Action a)
{
Initialize();
while (numThreads >= maxThreads)
{
Thread.Sleep(1);
}
Interlocked.Increment(ref numThreads);
ThreadPool.QueueUserWorkItem(RunAction, a);
return null;
}
private static void RunAction(object action)
{
try
{
((Action)action)();
}
catch
{
}
finally
{
Interlocked.Decrement(ref numThreads);
}
}
void OnDisable()
{
if (current == this)
{
current = null;
}
}
public struct DelayedQueueItem
{
public float time;
public Action action;
}
}