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.
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.
var workerQueue = new Queue<CustomWorker>();
private void SelectTreeViewCheckBox(object sender)
{
CustomWorker.QueueWorker(
this.workerQueue,
sender,
(x, e) =>
{
},
(x, e) =>
{
},
(e) =>
{
},
(x, e) =>
{
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