using System; using System.Collections.Generic; using System.Threading; using UnityEngine; namespace SoyEngine { public class Loom : MonoBehaviour { public static int MaxThreads = Environment.ProcessorCount + 1; private readonly Queue<Action> _taskQueue = new Queue<Action>(); private readonly List<Action> _actions = new List<Action>(); private readonly List<Action> _currentActions = new List<Action>(); private readonly List<Loom.DelayedQueueItem> _currentDelayed = new List<Loom.DelayedQueueItem>(); private readonly List<Loom.DelayedQueueItem> _delayed = new List<Loom.DelayedQueueItem>(); private static int _numThreads; private static Loom _current; private static bool _initialized; private static Loom Current { get { Loom.Initialize(); return Loom._current; } } public static void Init() { Loom.Initialize(); } private void Awake() { Loom._current = this; Loom._initialized = true; } private static void Initialize() { if (Loom._initialized || !Application.isPlaying) return; Loom._initialized = true; GameObject gameObject = new GameObject(nameof (Loom)); UnityEngine.Object.DontDestroyOnLoad((UnityEngine.Object) gameObject); Loom._current = gameObject.AddComponent<Loom>(); } public static void QueueOnMainThread(Action action) { Loom.QueueOnMainThread(action, 0L); } public static void QueueOnMainThread(Action action, long millis) { if ((UnityEngine.Object) Loom.Current == (UnityEngine.Object) null) return; if (millis > 0L) { lock (Loom.Current._delayed) Loom.Current._delayed.Add(new Loom.DelayedQueueItem() { Time = DateTimeUtil.GetNowTicks() + millis * 10000L, Action = action }); } else { lock (Loom.Current._actions) Loom.Current._actions.Add(action); } } public static void RunAsync(Action a) { Loom.Initialize(); lock (Loom.Current._taskQueue) { if (Loom._numThreads >= Loom.MaxThreads) { Loom.Current._taskQueue.Enqueue(a); } else { ++Loom._numThreads; ThreadPool.QueueUserWorkItem(new WaitCallback(Loom.RunAction), (object) a); } } } private static void RunAction(object obj) { LogHelper.Debug("Loom Thread Start, ThreadId: " + (object) Thread.CurrentThread.ManagedThreadId); Action action = (Action) obj; while (true) { try { action(); } catch (Exception ex) { LogHelper.Error(ex.ToString()); } lock (Loom.Current._taskQueue) { if (Loom.Current._taskQueue.Count > 0) { action = Loom.Current._taskQueue.Dequeue(); } else { --Loom._numThreads; break; } } } LogHelper.Debug("Loom Thread End, ThreadId: " + (object) Thread.CurrentThread.ManagedThreadId); } private void OnDisable() { if (!((UnityEngine.Object) Loom._current == (UnityEngine.Object) this)) return; Loom._current = (Loom) null; } private void Update() { lock (this._actions) { this._currentActions.Clear(); this._currentActions.AddRange((IEnumerable<Action>) this._actions); this._actions.Clear(); } foreach (Action currentAction in this._currentActions) { try { currentAction(); } catch (Exception ex) { LogHelper.Error(ex.ToString()); } } long now = DateTimeUtil.GetNowTicks(); lock (this._delayed) { this._currentDelayed.Clear(); this._currentDelayed.AddRange((IEnumerable<Loom.DelayedQueueItem>) this._delayed.FindAll((Predicate<Loom.DelayedQueueItem>) (d => d.Time <= now))); foreach (Loom.DelayedQueueItem delayedQueueItem in this._currentDelayed) this._delayed.Remove(delayedQueueItem); } foreach (Loom.DelayedQueueItem delayedQueueItem in this._currentDelayed) delayedQueueItem.Action(); } public struct DelayedQueueItem { public Action Action; public long Time; } } }
一个方便的多线程任务管理脚本
最新推荐文章于 2024-04-18 19:02:14 发布