private IEnumerator WaitForCompletion() { if (DebugMode) Debug.Log(" ----- WaitForCompletion: " + Thread.CurrentThread.ManagedThreadId); while (true) { //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 (DebugMode) Debug.Log(" ----- Coroutine knows its done!"); IThreadWorkerObject[] workedObjects = GetWorkerObjectsFromPackages(); workData.Dispose(); workData = null; _shedularBusy = false; if (onCompleteCallBack != null) onCompleteCallBack(workedObjects); }
/// <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(); } Monitor.PulseAll(workData.workerPackages); } //At this point in code, _isBusy should be set to FALSE, by the providerThread; if (sleepTillAborted && isBusy) { while (_providerThreadBusy) Thread.Sleep(1); } } workData = null; }
/// <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(); 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! -------------------- } }