public static void UpdateThreads() //called each time any thread is complete { try{ if (!on || queue.Count == 0) { return; } #if WDEBUG if (IsMainThread) { Profiler.BeginSample("Update Threads"); } #endif int threadsRunning = 0; //current number of threads then multithreading is on //calculating number of threads running int queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { if (queue[i].stage == Stage.threadRunning) { threadsRunning++; } } //guard if all possible threads already started: exit with no queue locking if (threadsRunning >= maxThreads) { #if WDEBUG if (IsMainThread) { Profiler.EndSample(); } #endif return; } //staring new threads lock (queue) while (threadsRunning < maxThreads) { //finding suitable worker with highest priority float maxProirity = -2000000; // int maxProirityNum = -1; ThreadWorker maxPriorityWorker = null; queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { ThreadWorker worker = queue[i]; if (worker == null) { continue; } if (worker.priority < maxProirity) { continue; } if (worker.stage != Stage.threadEnqueued) { continue; //if object destroyed or other stage } if (worker.threadCondition != null && !worker.threadCondition()) { continue; } maxPriorityWorker = worker; maxProirity = worker.priority; // maxProirityNum = i; } //no suitable threads if (maxPriorityWorker == null) { break; } //starting thread //lock (maxPriorityWorker.locker) Monitor.Enter(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = true; try { if (maxPriorityWorker.stage != Stage.threadEnqueued) { return; //this could happen if two threads selecting one worker, or worker stopped while being selected } if (logging) { Log(maxPriorityWorker, "Refresh:ThreadSelected (max" + maxProirity + ") "); } threadsRunning++; if (multithreading) { maxPriorityWorker.thread = new System.Threading.Thread(maxPriorityWorker.ThreadFn); maxPriorityWorker.thread.IsBackground = true; maxPriorityWorker.SwitchStage(Stage.threadRunning, "Refresh: start thread"); //before actually starting maxPriorityWorker.thread.Start(); } else { maxPriorityWorker.ThreadFn(); if (IsMainThread) { UnityEngine.Profiling.Profiler.EndSample(); } if (oneThreadPerFrame) { break; } } } finally { Monitor.Exit(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = false; } } #if WDEBUG if (IsMainThread) { Profiler.EndSample(); } #endif } catch (System.Exception e) { Debug.LogError("Spinner Error: " + e); } }
/// <summary> /// 更新应用 /// </summary> public static void UpdateApply() { if (!on || queue.Count == 0) { return; } #if WDEBUG Profiler.BeginSample("Update Apply"); #endif var timer = new System.Diagnostics.Stopwatch(); timer.Start(); while (timer.ElapsedMilliseconds < maxApplyTime) { //if couroutine has started - moving coroutine if (CurrentCoroutine != null) { currentCoroutineWorker.CoroutineFn(); continue; } //finding suitable worker with highest priority float maxProirity = -2000000; // int maxProirityNum = -1; ThreadWorker maxPriorityWorker = null; int queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { ThreadWorker worker = queue[i]; if (worker == null) { continue; //if object destroyed } if (worker.priority < maxProirity) { continue; } if (worker.stage != Stage.applyEnqueued && worker.stage != Stage.prepareEnqueued && worker.stage != Stage.coroutineEnqueued && worker.stage != Stage.coroutineRunning) { continue; //other stage } if (worker.stage == Stage.prepareEnqueued && worker.prepareCondition != null && !worker.prepareCondition()) { continue; } if (worker.stage == Stage.applyEnqueued && worker.applyCondition != null && !worker.applyCondition()) { continue; //if apply condition has not met } if (worker.stage == Stage.coroutineEnqueued && worker.coroutineCondition != null && !worker.coroutineCondition()) { continue; //if coroutine condition has not met (note that conditions is checked only before starting coroutine) } maxPriorityWorker = worker; maxProirity = worker.priority; // maxProirityNum = i; } //no suitable applies if (maxPriorityWorker == null) { break; } //apply //lock (maxPriorityWorker.locker) Monitor.Enter(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = true; try { if (logging) { Log(maxPriorityWorker, "Refresh:ApplyPrepSelected"); } if (maxPriorityWorker.stage == Stage.prepareEnqueued) { //maxPriorityWorker.SwitchStage(Stage.applyRunning); maxPriorityWorker.PrepareFn(); } if (maxPriorityWorker.stage == Stage.applyEnqueued) { //maxPriorityWorker.SwitchStage(Stage.applyRunning); maxPriorityWorker.ApplyFn(); } if (maxPriorityWorker.stage == Stage.coroutineEnqueued || maxPriorityWorker.stage == Stage.coroutineRunning) { maxPriorityWorker.CoroutineFn(); } } finally { Monitor.Exit(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = false; } } #if WDEBUG Profiler.EndSample(); #endif }