/// <summary>
 /// Convenience-Method: Call an action either immedately or queue it to MainThread
 /// </summary>
 /// <param name="act">the action</param>
 /// <param name="usingCoroutine">queue action to async-main-queue</param>
 /// <returns>Future that tells when or if the action is called</returns>
 public override AsyncFuture Call(Action act, bool usingCoroutine)
 {
     if (usingCoroutine)
     {
         // queue to async-queue
         return(_asyncManager.AddToMainThread(act));
     }
     else
     {
         var result = new AsyncFuture()
         {
             finished = true
         };
         // immediately call
         act();
         return(result);
     }
 }
        /// <summary>
        /// Add an action to be executated queued making sure to not take more time than set in MAIN_THREAD_MAX_MS (more or less)
        /// </summary>
        /// <param name="act"></param>
        public override AsyncFuture AddToMainThread(Action act)
        {
            var result = new AsyncFuture()
            {
                finished = false
            };

            workerMainThread.actions.Enqueue(act);
            workerMainThread.actions.Enqueue(() => { result.finished = true; });
            // start the worker to process the queue if not running
            if (disposableMainThreadWorker == null)
            {
                disposableMainThreadWorker = Observable.FromMicroCoroutine((cToken) => CoRoutineMainThreadWorker()).Subscribe(_ => {
                    disposableMainThreadWorker = null;
                });
            }
            return(result);
        }
        /// <summary>
        /// Add an action and its callback
        /// </summary>
        /// <param name="act"></param>
        /// <param name="onFinished"></param>
        public override AsyncFuture AddToWorkerThread(Action act, Action onFinished)
        {
            var result = new AsyncFuture()
            {
                finished = false
            };

            workerWorkerThread.actions.Enqueue(act);
            workerWorkerThread.actions.Enqueue(() => { result.finished = true; });
            if (onFinished != null)
            {
                workerWorkerThread.actions.Enqueue(onFinished);
            }
            if (disposableWorker == null)
            {
                disposableWorker = Observable.Start(ThreadWorkerAction).ObserveOnMainThread().Subscribe(_ => {
                    disposableWorker = null;
                });
            }
            return(result);
        }
        /// <summary>
        /// Add an action and its callback
        /// </summary>
        /// <param name="act"></param>
        /// <param name="onFinished"></param>
        public override AsyncFuture AddToWorkerThread(Action act, Action onFinished, bool global = false)
        {
            if (workerThreadRemoveNotGlobalActions && global == false)
            {
                Debug.LogWarning("AsyncManager doesn't accept non global actions atm. Skipping");
                return(new AsyncFuture()
                {
                    finished = true
                });
            }

            AsyncFuture result = new AsyncFuture()
            {
                finished = false
            };

            workerWorkerThread.actions.Enqueue(new AsyncAction()
            {
                action = act, global = global
            });
            workerWorkerThread.actions.Enqueue(new AsyncAction()
            {
                action = () => { result.finished = true; }, global = global
            });
            if (onFinished != null)
            {
                workerWorkerThread.actions.Enqueue(new AsyncAction()
                {
                    action = onFinished, global = global
                });
            }
            if (disposableWorker == null)
            {
                disposableWorker = Observable.Start(ThreadWorkerAction).ObserveOnMainThread().Subscribe(_ => {
                    disposableWorker.Dispose();
                    disposableWorker = null;
                });
            }
            return(result);
        }
 /// <summary>
 /// Convenience-Method: Call an action either immedately or queue it to MainThread
 /// </summary>
 /// <param name="act">the action</param>
 /// <param name="usingCoroutine">queue action to async-main-queue</param>
 /// <returns>Future that tells when or if the action is called</returns>
 public override AsyncFuture Call(Action act, bool usingCoroutine, bool global)
 {
     if (usingCoroutine)
     {
         // queue to async-queue
         return(_asyncManager.AddToMainThread(act, global));
     }
     else
     {
         AsyncFuture result = new AsyncFuture()
         {
             finished = true
         };
         // immediately call
         try {
             act();
         }
         catch (Exception e) {
             Debug.LogError("Catched AsyncManager.Call(Mainthread-immediate)-Exception:" + e + "\n" + e.StackTrace);
         }
         return(result);
     }
 }