//--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION -------------------------------------- //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION -------------------------------------- //--------------------------------------- EXTRA COMMANDS & ACTIONS -------------------------------------- //--------------------------------------- EXTRA COMMANDS & ACTIONS -------------------------------------- #region EXTRA COMMANDS & ACTIONS /// <summary> /// Aborts all worker processes currently queued. /// </summary> /// <param name="sleepTillAborted">if true: Makes sure that after invoking "AbortASyncThreads" the ThreadPoolSheduler is available again, but halts the MainThread while waiting for the other threads to finish</param> public void AbortASyncThreads(bool sleepTillAborted = false) { if (!_providerThreadBusy) { return; } _isAborted = true; StopCoroutine("WaitForCompletion"); if (workData != null && workData.workerPackages != null) { lock (workData.workerPackages) { foreach (ThreadWorkStatePackage package in workData.workerPackages) { if (package.running && !package.finishedWorking) { package.workerObject.AbortThreadedWork(); } } } //At this point in code, _isBusy should be set to FALSE, by the providerThread; if (sleepTillAborted && isBusy) { while (_providerThreadBusy) { Thread.Sleep(1); } } } workData = null; }
//--------------------------------------- UNITY MONOBEHAVIOUR COMMANDS -------------------------------------- //--------------------------------------- UNITY MONOBEHAVIOUR COMMANDS -------------------------------------- //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION -------------------------------------- //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION -------------------------------------- #region UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION /// <summary> /// Unlike "StartMultithreadedWorkloadExecution", you will have to build your own IThreadWorkerObject. /// Downside: It requires some extra work. Upside: you got more controll over what goes in and comes out /// Infact: You can create you own polymorphed IThreadWorkerObject-array, each ellement being a completely different type. For example: the statemachines of enemies are IThreadWorkerObject's and the array contains completely different classes with enemies/AI-behaviours. /// </summary> /// <param name="workerObjects">An array of IThreadWorkerObject objects to be handled by the threads. If you want multiple cores/threads to be active, make sure that the number of IThreadWorkerObject's proves matches/exeeds your preferred number maxWorkingThreads. </param> /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param> /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param> /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param> /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param> /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param> public void StartASyncThreads(IThreadWorkerObject[] workerObjects, ThreadPoolSchedulerEvent onCompleteCallBack, ThreadedWorkCompleteEvent onPackageExecuted = null, int maxThreads = -1, bool safeMode = true) { MainThreadWatchdog.Init(); MainThreadDispatcher.Init(); Debug.Log("ExecuteThreadedWork " + workerObjects.Length); if (_shedularBusy) { Debug.LogError("You are trying the start a new ASync threading-process, but is still Busy!"); return; } if (workerObjects == null || workerObjects.Length == 0) { Debug.LogError("Please provide an Array with atleast \"IThreadWorkerObject\"-object!"); return; } if (!ForceToMainThread) { _isAborted = false; this.onCompleteCallBack = onCompleteCallBack; this.onWorkerObjectDoneCallBack = onPackageExecuted; _shedularBusy = true; _providerThreadBusy = true; StartCoroutine("WaitForCompletion"); //--------------- Start Waiting for the Provider-thread to complete -------------------- workData = new ASyncThreadWorkData(workerObjects, safeMode, maxThreads); Thread providerThread = new Thread(new ThreadStart(InvokeASyncThreadPoolWork)); providerThread.Start(); //--------------- Start Waiting for the Provider-thread to complete -------------------- } else { //--------------- Execute all work in one bunch! -------------------- StartCoroutine(WaitAndExecuteWorkerObjects(workerObjects)); //--------------- Execute all work in one bunch! -------------------- } }
public void StartASyncThreads(IThreadWorkerObject[] workerObjects, ThreadPoolSchedulerEvent onCompleteCallBack, ThreadedWorkCompleteEvent onPackageExecuted = null, int maxThreads = -1, bool safeMode = true) { bool shedularBusy = this._shedularBusy; if (shedularBusy) { Debug.LogError("You are trying the start a new ASync threading-process, but is still Busy!"); } else { bool flag = workerObjects == null || workerObjects.Length == 0; if (flag) { Debug.LogError("Please provide an Array with atleast \"IThreadWorkerObject\"-object!"); } else { this._isAborted = false; this._shedularBusy = true; this._providerThreadBusy = true; this.onCompleteCallBack = onCompleteCallBack; this.onWorkerObjectDoneCallBack = onPackageExecuted; bool flag2 = !this.ForceToMainThread; if (flag2) { base.StartCoroutine("WaitForCompletion"); this.workData = new ASyncThreadWorkData(workerObjects, safeMode, maxThreads); this.providerThread = new Thread(new ThreadStart(this.InvokeASyncThreadPoolWork)); this.providerThread.Start(); } else { base.StartCoroutine(this.WaitAndExecuteWorkerObjects(workerObjects)); } } } }
private IEnumerator WaitForCompletion() { if (DebugMode) { Debug.Log(" ----- WaitForCompletion: " + Thread.CurrentThread.ManagedThreadId); } while (!_isAborted) { //After waiting a while, in the meantime it might have finished itself, or got aborted! yield return(new WaitForSeconds(WaitForSecondsTime)); if (_isAborted) { break; } //--------------- fire events while still working -------------------- int finishedObjectsCount = GetFinishedPackagesCount(); if (finishedObjectsCount == workData.workerPackages.Length) { break; } int unhandledPackagesCount = GetUnhandledFinishedPackagesCount(); if (DebugMode) { Debug.Log(" ----- unhandledPackages: " + unhandledPackagesCount + " ( out of: " + finishedObjectsCount + " completed so far...)"); } if (unhandledPackagesCount > 0) { foreach (ThreadWorkStatePackage package in workData.workerPackages) { if (package.finishedWorking && !package.eventFired) { if (onWorkerObjectDoneCallBack != null) { onWorkerObjectDoneCallBack(package.workerObject); } package.eventFired = true; } } } //--------------- fire events while still working -------------------- } if (!_isAborted) { if (DebugMode) { Debug.Log(" ----- Coroutine knows its done!"); } IThreadWorkerObject[] workedObjects = GetWorkerObjectsFromPackages(); workData.Dispose(); workData = null; _shedularBusy = false; if (onCompleteCallBack != null) { onCompleteCallBack(workedObjects); } } }
private IEnumerator WaitForCompletion() { while (true) { int num = 0; if (num != 0) { if (num != 1) { break; } bool isAborted = this._isAborted; if (isAborted) { goto Block_4; } int finishedPackagesCount = this.GetFinishedPackagesCount(); bool flag = finishedPackagesCount == this.workData.workerPackages.Length; if (flag) { goto Block_5; } int unhandledFinishedPackagesCount = this.GetUnhandledFinishedPackagesCount(); bool debugMode = this.DebugMode; if (debugMode) { Debug.Log(string.Concat(new object[] { " ----- unhandledPackages: ", unhandledFinishedPackagesCount, " ( out of: ", finishedPackagesCount, " completed so far...)" })); } bool flag2 = unhandledFinishedPackagesCount > 0; if (flag2) { ThreadWorkStatePackage[] array = this.workData.workerPackages; for (int i = 0; i < array.Length; i++) { ThreadWorkStatePackage threadWorkStatePackage = array[i]; bool flag3 = threadWorkStatePackage.finishedWorking && !threadWorkStatePackage.eventFired; if (flag3) { bool flag4 = this.onWorkerObjectDoneCallBack != null; if (flag4) { this.onWorkerObjectDoneCallBack(threadWorkStatePackage.workerObject); } threadWorkStatePackage.eventFired = true; } threadWorkStatePackage = null; } array = null; } } else { bool debugMode2 = this.DebugMode; if (debugMode2) { num++; Debug.Log(" ----- WaitForCompletion: " + Thread.CurrentThread.ManagedThreadId); } } if (this._isAborted) { goto IL_21E; } yield return(new WaitForSeconds(this.WaitForSecondsTime)); } yield break; Block_4: Block_5: IL_21E: bool flag5 = !this._isAborted; if (flag5) { bool debugMode3 = this.DebugMode; if (debugMode3) { Debug.Log(" ----- Coroutine knows its done!"); } IThreadWorkerObject[] finishedObjects = this.GetWorkerObjectsFromPackages(); this.workData.Dispose(); this.workData = null; this._shedularBusy = false; bool flag6 = this.onCompleteCallBack != null; if (flag6) { this.onCompleteCallBack(finishedObjects); } finishedObjects = null; } yield break; }