/ .Net

BackgroundWorker UserStates

Definition:
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Intro

I ran into a problem when I wanted to create an application to sync my savegames to Dropbox and I've found a powerful solution.

The problem

I needed to use a Backgroundworker in my application so that I could execute code without my UI freezing. Now the problem was that the Backgroundworker only has 1 ReportUpdate function. My application has 3 progress bars that show the backup progress.

[caption id="attachment_672" align="alignnone" width="622" caption="Note that the application has 3 progress bars."]CloudSave Screenshot[/caption]

As you can see on the image, I'm using 3 progress bars to notify the user of the progress.

  1. Is the games progress. As you can see we currently have 2 games to process.
  2. Is the files process, this indicates how many files have to be uploaded/have been uploaded.
  3. Is the upload progress of the current file.
So how do we control these 3 progress bars using 1 BackgroundWorker? Using UserStates!

The solution

We will use UserStates to solve this problem.

As we can see in the documentation, the userState is simply an Object. (ref. http://msdn.microsoft.com/en-us/library/a3zbdb1t.aspx)
So we can pass anything we like from the BackgroundWorker to our GUI.

So, let me show you some code. In my example I'll simply be passing a String as the userstate. (To keep things simple)
You can also pass an array of data or even a custom object that you've made yourself. Just keep in mind not to send too much overhead.

The BackgroundWorker code

When we've finished processing a game, I'll simply call the ReportProgress function and pass the string "games" as the UserState.

[csharp]worker.ReportProgress(Convert.ToInt32(((double)gamesProcessed / (double)numberOfGames) *100), "games");[/csharp]

I'll do the same for the files progress and the upload progress.

[csharp]worker.ReportProgress(Convert.ToInt32((double)currentFileIndex / (double)files.Count * 100), "files");[/csharp]

The upload progress is actually in a different function that recieves the progress as an argument, but that's not completely relevant.

[csharp]_worker.ReportProgress(e.PercentageProgress, "upload"); [/csharp]

The GUI code

So now that we've reported the progress, we have to visualize it on the GUI.

[csharp]
_worker.ProgressChanged += delegate(object sender1, ProgressChangedEventArgs e1)
{
if(Equals(e1.UserState, "games"))
{
pbNumberofGames.Value = e1.ProgressPercentage;
}
else if(Equals(e1.UserState,"upload"))
{
pbProgress.Value = e1.ProgressPercentage;
}
else if (Equals(e1.UserState,"files"))
{
pbFiles.Value = e1.ProgressPercentage;
}
};
[/csharp]

All we do here is update the right progress bar associated with the UserState. For example; If the UserState equals "games", we update the progress bar associated with the games progress. (the first progress bar, I've naded it pbNumberofGames)

And that's it. Now we can report an infinite amount of things from the Backgroundworker!
And you can create rich application when using a custom Object as the UserState.

~Michiel De Mey

Michiel De Mey

Michiel De Mey

Full-time geek, Full Stack Engineer and Full Metal Hero. Node.js, #Docker, API design, WebSec & IoT enthusiast. Former San Francisco resident.

Read More