public void RunAndWait(
            Action <object, DoWorkEventArgs> action,
            Action <object, RunWorkerCompletedEventArgs> actionComplete,
            int millisecondsTimeout)
        {
            using (var worker = new TaskWorker(null))
            {
                // can be rewritten to support cancelling by adding
                // the worker to the TasksQueue and implementing
                // worker.CancellationTokenSource.Token.WaitHandle.WaitOne
                worker.WorkerReportsProgress      = false;
                worker.WorkerSupportsCancellation = true;
                AutoResetEvent waitEvent = new AutoResetEvent(false);
                worker.DoWork += (sender, args) =>
                {
                    if (worker.CancellationPending == false && !worker.CancellationTokenSource.IsCancellationRequested)
                    {
                        if (action != null)
                        {
                            action.Invoke(sender, args);
                        }
                    }
                    else
                    {
                        args.Cancel = true;
                        return;
                    }
                };

                worker.RunWorkerCompleted += (sender, args) =>
                {
                    if (actionComplete != null)
                    {
                        actionComplete.Invoke(sender, args);
                    }
                    waitEvent.Set();
                };

                worker.RunWorkerAsync();
                var waitResult = waitEvent.WaitOne(millisecondsTimeout);
                if (waitResult == false)
                {
                    throw new TimeoutException("Task thread timed out.");
                }
            }
        }
        public void QueueWorkerWithDelay(
            Queue <TaskWorker> queue,
            object item,
            Action <object, DoWorkEventArgs> action,
            Action <object, RunWorkerCompletedEventArgs> actionComplete,
            Action <RunWorkerCompletedEventArgs> displayError,
            Action <object, ProgressChangedEventArgs> progressChange,
            int millisecondsDelay)
        {
            if (queue == null)
            {
                throw new ArgumentNullException("queue");
            }

            using (var worker = new TaskWorker(item))
            {
                worker.WorkerReportsProgress      = true;
                worker.WorkerSupportsCancellation = true;

                worker.ProgressChanged += (sender, args) =>
                {
                    if (worker.CancellationPending == false && progressChange != null)
                    {
                        progressChange.Invoke(sender, args);
                    }
                };

                worker.DoWork += (sender, args) =>
                {
                    if (worker.CancellationPending == false)
                    {
                        if (millisecondsDelay > 0)
                        {
                            var cancelled = worker.CancellationTokenSource.Token
                                            .WaitHandle.WaitOne(millisecondsDelay);

                            if (cancelled)
                            {
                                args.Cancel = true;
                                return;
                            }
                        }

                        if (action != null)
                        {
                            action.Invoke(sender, args);
                        }
                    }
                    else
                    {
                        args.Cancel = true;
                        return;
                    }
                };

                // This method may not fire if the worker is destroyed prematurely!
                worker.RunWorkerCompleted += (sender, args) =>
                {
                    if (actionComplete != null)
                    {
                        actionComplete.Invoke(sender, args);
                    }

                    if (queue.Count != 0)
                    {
                        queue.Dequeue();
                    }
                    if (queue.Count > 0)
                    {
                        var next = queue.Peek();

                        if (next.WorkerReportsProgress)
                        {
                            next.ReportProgress(0, "Performing operation...");
                        }

                        next.RunWorkerAsync(next.Sender);
                    }
                    else
                    {
                        if (displayError != null)
                        {
                            displayError.Invoke(args);
                        }
                    }
                };

                queue.Enqueue(worker);

                if (queue.Count > 0)
                {
                    var next = queue.Peek();
                    if (next.WorkerReportsProgress)
                    {
                        next.ReportProgress(0, "Performing operation...");
                    }

                    if (!next.CancellationPending && !next.IsBusy)
                    {
                        next.RunWorkerAsync(next.Sender);
                    }
                }
            }
        }