153 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C#
		
	
	
		
		
			
		
	
	
			153 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C#
		
	
	
|  | namespace Guru | ||
|  | { | ||
|  |     using UnityEngine; | ||
|  | 	using System.Collections.Generic; | ||
|  | 	using System; | ||
|  | 	using System.Threading; | ||
|  | 	using System.Linq; | ||
|  | 
 | ||
|  | 	public class Loom : MonoBehaviour | ||
|  | 	{ | ||
|  | 		public static int maxThreads = 8; | ||
|  | 		static int numThreads; | ||
|  | 
 | ||
|  | 		private static Loom _current; | ||
|  | 		private int _count; | ||
|  | 		public static Loom Current | ||
|  | 		{ | ||
|  | 			get | ||
|  | 			{ | ||
|  | 				Initialize(); | ||
|  | 				return _current; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		void Awake() | ||
|  | 		{ | ||
|  | 			_current = this; | ||
|  | 			initialized = true; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		static bool initialized; | ||
|  | 
 | ||
|  | 		static void Initialize() | ||
|  | 		{ | ||
|  | 			if (!initialized) | ||
|  | 			{ | ||
|  | 				if (!Application.isPlaying) | ||
|  | 					return; | ||
|  | 				 | ||
|  | 				initialized = true; | ||
|  | 				var g = new GameObject("Loom"); | ||
|  | 				_current = g.AddComponent<Loom>(); | ||
|  | 				DontDestroyOnLoad(g); // 增加GO持久化 | ||
|  | 			} | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		private List<Action> _actions = new List<Action>(); | ||
|  | 		public struct DelayedQueueItem | ||
|  | 		{ | ||
|  | 			public float time; | ||
|  | 			public Action action; | ||
|  | 		} | ||
|  | 		private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>(); | ||
|  | 
 | ||
|  | 		List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>(); | ||
|  | 
 | ||
|  | 		public static void QueueOnMainThread(Action action) | ||
|  | 		{ | ||
|  | 			QueueOnMainThread(action, 0f); | ||
|  | 		} | ||
|  | 		public static void QueueOnMainThread(Action action, float time) | ||
|  | 		{ | ||
|  | 			if (time != 0) | ||
|  | 			{ | ||
|  | 				lock (Current._delayed) | ||
|  | 				{ | ||
|  | 					Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action }); | ||
|  | 				} | ||
|  | 			} | ||
|  | 			else | ||
|  | 			{ | ||
|  | 				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; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		List<Action> _currentActions = new List<Action>(); | ||
|  | 
 | ||
|  | 		// Update is called once per frame | ||
|  | 		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 StartUp() | ||
|  | 		{ | ||
|  | 			if (initialized || null != _current) return;  | ||
|  | 			Initialize(); | ||
|  | 		} | ||
|  | 	} | ||
|  | } |