Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / threads

Background Worker Queue in C#

4.74/5 (12 votes)
27 Aug 2015CPOL1 min read 31.3K  
How to implement the Queue of Background Worker

Introduction

I need to create the Queue of Backgroundworker so i can add actions to it and Run action when first one is completed till the Queue has something to run.

Background

I found it usefull for TreeView item selection where on selection we need to execute some action but sequentially without freezing the UI.

Using the code

CustomWorker class is a wrapper class of Backgroundworker which has sender property, sender property can be set as any sender where operation is being performed, in my case sender was TreeView checkbox selected item.

"QueueWorker" function accepts the queue object, sender and all required actions to be performed for each worker, in this example i have taken DoWork, WorkerCompleted, ProgressChanged and one custom action which i invoke to display errors if any when worker queue is empty.

C#
public class CustomWorker : BackgroundWorker
    {
        public CustomWorker(object sender)
        {
            this.Sender = sender;
        }

        public object Sender { get; private set; }

        public static void QueueWorker(
                            Queue<CustomWorker> queue,
                            object item,
                            Action<object, DoWorkEventArgs> action,
                            Action<object, RunWorkerCompletedEventArgs> actionComplete,
                            Action<RunWorkerCompletedEventArgs> displayError,
                            Action<object, ProgressChangedEventArgs> progressChange)
        {
            if (queue == null)
                throw new ArgumentNullException("queue");

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

                worker.ProgressChanged += (sender, args) =>
                {
                    progressChange.Invoke(sender, args);
                };

                worker.DoWork += (sender, args) =>
                {
                    action.Invoke(sender, args);
                };

                worker.RunWorkerCompleted += (sender, args) =>
                {
                    actionComplete.Invoke(sender, args);
                    queue.Dequeue();
                    if (queue.Count > 0)
                    {
                        var next = queue.Peek();
                        next.ReportProgress(0, "Performing operation...");
                        next.RunWorkerAsync(next.Sender);
                    }
                    else
                        displayError.Invoke(args);
                };

                queue.Enqueue(worker);
                if (queue.Count == 1)
                {
                    var next = queue.Peek();
                    next.ReportProgress(0, "Performing operation...");
                    next.RunWorkerAsync(next.Sender);
                }
            }
        }
    }

Usage of CustomWorker is as below, a empty object of Queue, sender and actions are passed.

QueueWorker function will update the queue by creating the background worker for each action and queue them for execution.

C#
var workerQueue = new Queue<CustomWorker>();
private void SelectTreeViewCheckBox(object sender)
        {
            CustomWorker.QueueWorker(
                this.workerQueue,
                sender,
                (x, e) =>
                {
                    //// some custom do work logic.
                },
                (x, e) =>
                {
                    //// some custom completed logic.
                },
                (e) =>
                {
                    //// some custom display error logic.
                },
                (x, e) =>
                {
                    //// Progress change logic.
                    this.ProgressValue = e.ProgressPercentage;
                    this.Status = e.UserState.ToString();
                });
        }

Points of Interest

I was using the Backgroundworker for performing some operation on each checkbox selection of treeview and all selection have some dependency, so i have to use some locking to avoid updating objects by different workers at same time, once i implemented this Queue of Workers i didn't require lock and handling of selection became seamless.

History

1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)