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! --------------------
            }
        }