Click here to Skip to main content
12,896,849 members (56,948 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


79 bookmarked
Posted 23 Jan 2012

BackgroundWorker helper

, 17 Jan 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
A class that may shorten your time spent with BackgroundWorker, and handles some logics of working with it.


The BackgroundWorker class is used to manage work that is done in a background thread and report progress to the UI, avoiding cross-threading problems. Implementing all BackgroundWorker logic is a bit dirty and does take place in your code.

In this article I present a wrapper class which handles some work you usually do. It's useful for situations when you need execution of a set of independent tasks.

An example might be sending mail to several recipients or processing a set of images.

Using the code

The BWHelper class aggregates the actions that should be done. It handles BackgroundWorker.DoWork and checks whether the user decided to use parallel or sequential execution. Then it executes all Actions, checking before each execution if cancellation was asked.

The class also computes the percentage done and the probable time left (based on the average execution time of completed tasks).

public class BWHelper
    private IEnumerable<Action> toDo;
    private DateTime startTime;
    private bool isParallel = false;
    private BackgroundWorker worker;

    private ValueMonitor<int> percentageProgress = new ValueMonitor<int>(0);
    private ValueMonitor<TimeSpan> timeLeft = new ValueMonitor<TimeSpan>(TimeSpan.MaxValue);

    public void SetActionsTodo( IEnumerable<Action> toDoActions)
        toDo = toDoActions;

    public bool IsParallel
        get { return isParallel; }
        set { isParallel = value; }

    public IValueMonitor<TimeSpan> TimeLeft { get { return timeLeft; } }

    public BWHelper(BackgroundWorker aWorker)
        worker = aWorker;
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;
        percentageProgress.ValueChanged += 
                   new ValueChangedDelegate<int>(percentageProgress_ValueChanged);

        worker.DoWork += new DoWorkEventHandler(worker_DoWork);

    public BWHelper(IEnumerable<Action> actionsToDo, BackgroundWorker aWorker):this(aWorker)
        toDo = actionsToDo;

    public int Total
            if (toDo == null) return 0;
            return toDo.Count();

    private void percentageProgress_ValueChanged(int oldValue, int newValue)

    private void  worker_DoWork(object sender, DoWorkEventArgs e)
        if (toDo == null)
            throw new InvalidOperationException("You must provide actions to execute");
        int total = toDo.Count();
        startTime = DateTime.Now;
        int current = 0;
        if (isParallel == false)
            foreach (var next in toDo)
                if (worker.CancellationPending == true) return;
                percentageProgress.Value = (int)((double)current / (double)total * 100.0);
                double passedMs = (DateTime.Now - startTime).TotalMilliseconds;
                double oneUnitMs = passedMs / current;
                double leftMs = (total - current) * oneUnitMs;
                timeLeft.Value = TimeSpan.FromMilliseconds(leftMs);
            Parallel.For(0, total - 1,
                (index, loopstate) => 

                        if (worker.CancellationPending == true) loopstate.Stop();
                        Interlocked.Increment(ref current);

                        percentageProgress.Value = (int)((double)current / (double)total * 100.0);
                        double passedMs = (DateTime.Now - startTime).TotalMilliseconds;
                        double oneUnitMs = passedMs / current;
                        double leftMs = (total - current) * oneUnitMs;
                        timeLeft.Value = TimeSpan.FromMilliseconds(leftMs);


The ValueMonitor class is intensively used for int and TimeSpan value types. Note that because TimeLeft change is signaled by means of the ValueMonitor.ValueChanged event rather than doing this using BackgroundWorker, you should implement the cross-threading logic yourself. In the example project, for the sake of simplicity and because I'm lazy, the CheckForIllegelCrossThreadCalls property is set to true.

The example project is a Windows Forms application which executes "useful" tasks, each taking 200 ms. It also shows the possible time left. You also may choose either parallel or sequential execution.

When the Start button is hit, the following code is executed:

List<Action> actions = new List<Action>();
for (int i = 0; i< 100; i++)
    actions.Add( () => Thread.Sleep(200) );

helper.IsParallel = checkBoxUseParallel.Checked;

The things we gain from BWHelper are:

  • Percentage counting is concentrated in one place. You also don't have to worry about the ReportProgress method.
  • Average time left is measured. You may handle the BWHelper.TimeLeft.ValueChanged event to show this in the UI.
  • Easy switch between sequential and parallel actions execution.
  • Cancellation logic is also not your task.
  • The properties WorkerReportsProgress and WorkerSupportsCancellation are set to true in the constructor.

While we've got these advantages, it should be noted what this class can't provide:

  • BWHelper is not suitable when your Actions depend on results of each other.
  • Remember, that if some of your actions take too long, the cancellation may also take a long time.


  • Jan. 22, 2012 - First published.


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


About the Author

Software Developer Crypton-M
Ukraine Ukraine
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralVery good Pin
Robin Purbia21-Sep-15 23:16
memberRobin Purbia21-Sep-15 23:16 
QuestionNice post Pin
nexus_er22-Feb-14 8:05
membernexus_er22-Feb-14 8:05 
QuestionIt is great Pin
AmerZafar24-Aug-13 19:51
memberAmerZafar24-Aug-13 19:51 
GeneralVery good Pin
Tom mazur18-Jan-13 7:35
memberTom mazur18-Jan-13 7:35 
GeneralMy vote of 4 Pin
DavidSmithgf18-Jan-13 0:35
memberDavidSmithgf18-Jan-13 0:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170424.1 | Last Updated 17 Jan 2013
Article Copyright 2012 by kosmoh
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid