public static void Log(ThreadWorker iWorker, string iMessage, bool iLogToConsole = false) { #if WDEBUG if (!logging) { return; } if (Logs.Count > 50000) { Logs.RemoveRange(0, 20000); } var logEntity = new ThreadLogEntity { worker = iWorker, name = iMessage, stage = iWorker.stage, stop = iWorker.stop, threadId = Thread.CurrentThread.ManagedThreadId }; if (iWorker.threadCondition != null) { logEntity.threadCondition = iWorker.threadCondition() ? ThreadLogEntity.ConditionMet.True : ThreadLogEntity.ConditionMet.False; } if (iWorker.applyCondition != null) { logEntity.applyCondition = iWorker.applyCondition() ? ThreadLogEntity.ConditionMet.True : ThreadLogEntity.ConditionMet.False; } logEntity.time = DateTime.Now; logEntity.locked = iWorker.lockWasTaken; Logs.Add(logEntity); #endif if (iLogToConsole) { Loger.Error($"ThreadWorker::Log():Worker:{iWorker.name} {iMessage}"); } }
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); } }