using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; using UnityEngine; public struct DelayedQueueItem { public float time; public Action action; } public class Loom : MonoBehaviour { /// /// 最大线程数量 /// public static int maxThreads = 8; /// /// 线程数量 /// static int numThreads; private static Loom _currentLoom; public static Loom CurrentLoom { get { Initialize(); return _currentLoom; } } /// /// 是否已经初始化 /// static bool initialized; /// /// 作为初始化方法自己调用,可在初始化场景调用一次即可 /// public static void Initialize() { if (!initialized) { if (!Application.isPlaying) return; initialized = true; GameObject g = new GameObject("Loom"); //####永不销毁 DontDestroyOnLoad(g); _currentLoom = g.AddComponent(); } } /// /// 延迟执行的队列 /// private List _delayedQueueItems = new List(); /// /// 目前正在延迟执行的队列 /// private List _currentDelayedQueueItems = new List(); /// /// 新添加的ACTION /// private List _newActions = new List(); /// /// 不延迟执行 /// private List _CurrentNoDelayActions = new List(); public static void QueueOnMainThread(Action action) { QueueOnMainThread(action, 0f); } /// /// 添加到主线程执行 /// /// /// public static void QueueOnMainThread(Action action, float delayTime) { if (delayTime != 0) { if (CurrentLoom != null) { lock (CurrentLoom._delayedQueueItems) { CurrentLoom._delayedQueueItems.Add(new DelayedQueueItem { time = Time.time + delayTime, action = action }); } } } else { if (CurrentLoom != null) { lock (CurrentLoom._newActions) { CurrentLoom._newActions.Add(action); } } } } public static Thread RunAsync(Action action) { Initialize(); while (numThreads >= maxThreads) { //将当前线程挂起指定的毫秒数。 Thread.Sleep(1); } //递增线程数量(Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果) Interlocked.Increment(ref numThreads); //将方法排入队列以便执行。 此方法在有线程池线程变得可用时执行 ThreadPool.QueueUserWorkItem(RunAction, action); return null; } private static void RunAction(object action) { try { ((Action)action)(); } catch { } finally { //递减线程数量(Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果) Interlocked.Decrement(ref numThreads); } } void Update() { lock (_newActions) { _CurrentNoDelayActions.Clear(); _CurrentNoDelayActions.AddRange(_newActions); _newActions.Clear(); } foreach (var actionItem in _CurrentNoDelayActions) { actionItem(); } lock (_delayedQueueItems) { _currentDelayedQueueItems.Clear(); _currentDelayedQueueItems.AddRange(_delayedQueueItems.Where(d => d.time <= Time.time)); foreach (var item in _currentDelayedQueueItems) { _delayedQueueItems.Remove(item); } } foreach (var delayed in _currentDelayedQueueItems) { delayed.action(); } } void OnDisable() { if (_currentLoom == this) { _currentLoom = null; } } }