/// <summary> /// !IMPORTANT! This method should be called regularly within routines that take more then half a second to complete, to make sure IOS for example is able to force an application to sleep when it looses focus or gets puched to the background. /// This is a very light-weight check, internally it only needs to check two static booleans once everything is Initialized and running. /// You can use this without causing any serious overhead. /// Motivation: Sins Threads cannot be put asleep from the outside, it needs the be managed from within the thread itself, thats why this method was build. /// /// Example: /// for(int i = 0; i < 999999999; i++) /// { /// Loom.SleepOrAbortIfUnityInactive(); //Prevents IOS for example of killing this app because the threads won't sleep once your unity-app is puched to the background. /// //Do something heavy that will cause this routine to run more then 0.5 seconds. /// } /// </summary> public static void SleepOrAbortIfUnityInactive() { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); }
//--------------------------------------- EXTRA COMMANDS & ACTIONS -------------------------------------- //--------------------------------------- EXTRA COMMANDS & ACTIONS -------------------------------------- //--------------------------------------- .NET THREADPOOL IMPLEMENTATION -------------------------------------- //--------------------------------------- .NET THREADPOOL IMPLEMENTATION -------------------------------------- #region .NET THREADPOOL IMPLEMENTATION /// <summary> /// This method is the work-provider-method. It makes sure the .NET threadpool has things to do... /// This method is NOT invoked by the mainThread, therefor is safe to use WaitHandle.WaitAll / WaitAny without halting Unity's gameThread! /// </summary> public void InvokeASyncThreadPoolWork() { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); int totalWork = workData.workerPackages.Length; int startBurst = Mathf.Clamp(workData.maxWorkingThreads, 1, totalWork); if (DebugMode) { Debug.Log(" ----- InvokeASyncThreadPoolWork. startBurst: " + startBurst + ", totalWork: " + totalWork); } //--------------- Initial Startup burst -------------------- for (int i = 0; i < startBurst && !_isAborted; i++) { //Add to .NET ThreadPool if (workData.workerPackages[i] != null) { workData.workerPackages[i].started = true; ThreadPool.QueueUserWorkItem(workData.workerPackages[i].ExecuteThreadWork, i); } } //--------------- Initial Startup burst ---------------s----- if (DebugMode) { Debug.Log(" ----- Burst with WorkerObjects being processed!"); } //--------------- Create a new Thread to keep the Threadpool running & cores saturated! -------------------- workObjectIndex = startBurst; //at this point the amount of running WorkObjects/Threads is equal to the startBurst; while (workObjectIndex < totalWork && !_isAborted) { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); AutoResetEvent[] startedEvents = GetStartedPackageEvents(); if (startedEvents.Length > 0) { WaitHandle.WaitAny(startedEvents); } workData.workerPackages[workObjectIndex].started = true; ThreadPool.QueueUserWorkItem(workData.workerPackages[workObjectIndex].ExecuteThreadWork, workObjectIndex); workObjectIndex++; } //--------------- Create a new Thread to keep the Threadpool running & cores saturated! -------------------- if (DebugMode) { Debug.Log(" ----- all packages fed to the pool!"); } //--------------- Wait till all are finished! -------------------- //All WorkObjects have been set to work, but the last few Threads might still be pending! AutoResetEvent[] pendingEvents = GetStartedPackageEvents(); if (pendingEvents.Length > 0) { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); WaitHandle.WaitAll(pendingEvents); } //--------------- Wait till all are finished! -------------------- if (DebugMode) { Debug.Log(" ----- PROVIDER THREAD DONE"); } //DONE! _providerThreadBusy = false; }
public void InvokeASyncThreadPoolWork() { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); int num = this.workData.workerPackages.Length; int num2 = Mathf.Clamp(this.workData.maxWorkingThreads, 1, num); bool debugMode = this.DebugMode; if (debugMode) { Debug.Log(string.Concat(new object[] { " ----- InvokeASyncThreadPoolWork. startBurst: ", num2, ", totalWork: ", num })); } int num3 = 0; while (num3 < num2 && !this._isAborted) { bool flag = this.workData.workerPackages[num3] != null; if (flag) { this.workData.workerPackages[num3].started = true; ThreadPool.QueueUserWorkItem(new WaitCallback(this.workData.workerPackages[num3].ExecuteThreadWork), num3); } int num4 = num3; num3 = num4 + 1; } bool debugMode2 = this.DebugMode; if (debugMode2) { Debug.Log(" ----- Burst with WorkerObjects being processed!"); } this.workObjectIndex = num2; while (this.workObjectIndex < num && !this._isAborted) { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); AutoResetEvent[] startedPackageEvents = this.GetStartedPackageEvents(); bool flag2 = startedPackageEvents.Length > 0; if (flag2) { WaitHandle.WaitAny(startedPackageEvents); } this.workData.workerPackages[this.workObjectIndex].started = true; ThreadPool.QueueUserWorkItem(new WaitCallback(this.workData.workerPackages[this.workObjectIndex].ExecuteThreadWork), this.workObjectIndex); int num4 = this.workObjectIndex; this.workObjectIndex = num4 + 1; } bool debugMode3 = this.DebugMode; if (debugMode3) { Debug.Log(" ----- all packages fed to the pool!"); } AutoResetEvent[] startedPackageEvents2 = this.GetStartedPackageEvents(); bool flag3 = startedPackageEvents2.Length > 0; if (flag3) { UnityActivityWatchdog.SleepOrAbortIfUnityInactive(); WaitHandle.WaitAll(startedPackageEvents2); } bool debugMode4 = this.DebugMode; if (debugMode4) { Debug.Log(" ----- PROVIDER THREAD DONE"); } this._providerThreadBusy = false; }