154 lines
3.2 KiB
C#
154 lines
3.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using UnityEngine;
|
|
|
|
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;
|
|
}
|
|
} |