/// <summary>
        /// Execute a task in synchronized manner.
        /// </summary>
        /// <param name="task">Task to start</param>
        /// <param name="action">DuplicateTaskQueued</param>
        /// <returns>An Exception object on any failure within the task,
        /// or null if the task was successfully finished or cancelled.</returns>
        public static Exception RunTaskSynchronized(ThreadWorkerTaskBase task, DuplicateTaskQueued action)
        {
            if (IsTaskQueued(task.TaskID))
            {
                if (action == DuplicateTaskQueued.Ignore)
                {
                    return(null);
                }

                if (action != DuplicateTaskQueued.Allowed)                      // wait, or abort running task thread
                {
                    if (action == DuplicateTaskQueued.Abort)
                    {
                        AbortTask(task.TaskID);
                    }
                    if (action != DuplicateTaskQueued.Wait)
                    {
                        WaitForTask(task.TaskID);
                    }
                }
            }

            ThreadWorkerBase wc = task.GetWorkerInstance();

            queuedTasks.Add(task.TaskID, task);
            try {
                return(wc.LocalRunProcess());
            } finally {
                queuedTasks.Remove(task);
            }
        }
        /// <summary>
        /// Queue a task using a freshly created Thread.
        /// </summary>
        /// <param name="task">Task to start</param>
        /// <param name="action">DuplicateTaskQueued</param>
        /// <returns>True, if the task was successfully started, else false.</returns>
        public static bool StartTask(ThreadWorkerTaskBase task, DuplicateTaskQueued action)
        {
            if (waitForGlobalThreadResource)
            {
                // delay startup of the thread
                if (IsTaskWaitingForGlobalThreadResource(task.TaskID))
                {
                    if (action == DuplicateTaskQueued.Ignore)
                    {
                        return(false);
                    }
                    if (action != DuplicateTaskQueued.Allowed)
                    {
                        return(false);                          // we do not have to wait/abort, they are not yet even started anyway
                    }
                }

                TaskStartInfo startInfo = new TaskStartInfo(TaskStartInfo.StartMethod.ThreadStart, task, action);
                taskStartInfos.Enqueue(startInfo);
                return(true);
            }

            if (IsTaskQueued(task.TaskID))
            {
                if (action == DuplicateTaskQueued.Ignore)
                {
                    return(false);
                }

                if (action != DuplicateTaskQueued.Allowed)                      // wait, or abort running task thread
                {
                    if (action == DuplicateTaskQueued.Abort)
                    {
                        AbortTask(task.TaskID);
                    }
                    if (action != DuplicateTaskQueued.Wait)
                    {
                        WaitForTask(task.TaskID);
                    }
                }
            }

            ThreadWorkerBase wc = task.GetWorkerInstance();
            Thread           t  = new Thread(new ThreadStart(wc.RunProcess));

            t.IsBackground    = true;          //make them a daemon - prevent thread callback issues
            task.WorkerThread = t;
            t.Start();
            queuedTasks.Add(task.TaskID, task);
            return(true);
        }
        /// <summary>
        /// Queue a task using ThreadPool.
        /// </summary>
        /// <param name="task">Task to start</param>
        /// <param name="action">Duplicate task action</param>
        /// <returns>True, if the task was successfully queued up
        /// to the ThreadPool, else false.</returns>
        public static bool QueueTask(ThreadWorkerTaskBase task, DuplicateTaskQueued action)
        {
            if (waitForGlobalThreadResource)
            {
                // delay startup of the thread
                if (IsTaskWaitingForGlobalThreadResource(task.TaskID))
                {
                    if (action == DuplicateTaskQueued.Ignore)
                    {
                        return(false);                          // yet waiting
                    }
                    if (action != DuplicateTaskQueued.Allowed)
                    {
                        return(false);                          // we do not have to wait/abort, they are not yet even started anyway
                    }
                }

                TaskStartInfo startInfo = new TaskStartInfo(TaskStartInfo.StartMethod.ThreadPool, task, action);
                taskStartInfos.Enqueue(startInfo);
                return(true);
            }

            if (IsTaskQueued(task.TaskID))
            {
                if (action == DuplicateTaskQueued.Ignore)
                {
                    return(false);
                }

                if (action != DuplicateTaskQueued.Allowed)                      // wait, or abort running task thread
                {
                    if (action == DuplicateTaskQueued.Abort)
                    {
                        AbortTask(task.TaskID);
                    }
                    if (action != DuplicateTaskQueued.Wait)
                    {
                        WaitForTask(task.TaskID);
                    }
                }
            }

            queuedTasks.Add(task.TaskID, task);
            ThreadWorkerBase wc = task.GetWorkerInstance();

            return(ThreadPool.QueueUserWorkItem(new WaitCallback(wc.RunProcess)));
        }