Browsed by
Category: Threading

Progress Bars and the BackgroundWorker – C# & WPF

Progress Bars and the BackgroundWorker – C# & WPF

This is just a quick introduction on my implementation of using a progress bar in WPF and C#.
The first step is to create the progress bar itself, which is a built in WPF control. So create a dialog and place a progress bar control as so:

One thing to note here is that, in my opinion, for the tasks this implementation was originally designed for, an indeterminate progress bar would have been best. However I was tasked with implementing a progress bar which updated towards 100% so that users were aware of (roughly) how long was remaining on the process.
First, I modified the constructor of the dialog to accept two strings as a parameter, this sets the title on the dialog of the progress bar, and also sets a message on the dialog to inform the user of what’s happening (we’ll add a way to update this later). A private integer is added that will be used to update the progress bar incrementally if desired, and this value is just set to 5 by default.

Now in the .cs file for the progress bar we’ll need some methods to update the progress bar when necessary. For my project, I added three methods here.
One to update the progress which takes in a string and an integer as parameters. The string updates a label I placed above the progress bar to inform the user of what’s currently happening, while the integer sets the new value which moves the progress bar along:

The next method was to increment progress. This was added to provide a simpler way to update the progress bar at specified points in the process, giving a smoother motion to the updating of the progress bar:

And finally I added a method simply to set the increment amount so that it wouldn’t continuously need to be passed as a parameter throughout the process:

On these methods I’ve made the updates to the dialog through the use of a dispatcher. Because the methods that will be updating the progress bar are called from a BackgroundWorker, this is required to stop exceptions being raised by attempting to modify the dialog off of the main UI thread.
The next thing needed is to add a class for handling the BackgroundWorker so that methods can be run whilst updating the progress bar.
To start with I created the constructor and some private variables:

The main thing to note here is the Action that is passed in as a parameter. This is done so that you can have a single entry point that allows you to open and run the progress dialog, regardless of what method you’re wanting to use – provided they take the Progress Dialog as a parameter.
This constructor registers the created BackgroundWorker to the DoWork and RunWorkerCompleted events, initializes the progress dialog, starts the worker running asynchronously, and then displays the progress dialog to the user.
The RunWorkerCompleted event handler has been kept simple, here I just use the event to close the progress dialog as it’s no longer required, however you can add whatever you see fit in here:

And finally we create the DoWork event handler:

This event handler simply calls the Action that was passed in to the constructor earlier, passing in the progress dialog instance so that the method can update the progress. The Action is called inside a try-catch block as errors that are thrown on the BackgroundWorker may not be handled appropriately by exception handling elsewhere, so it would be wise to do so here.
And that’s it really!
An example of opening the dialog and running a method is like so:

Where MyDoWorkMethod is any method that accepts a ProgressDialog as a parameter.
As mentioned earlier, some parts of this implementation are less than ideal – primarily around the way the progress bar is updated for me. This could be avoided by using an indeterminate progress bar, as this isn’t being used for something we can accurately timebox such as a download or a loop performing a specific number of actions.
Another way would be not to pass the Action as a parameter and call logic directly in the DoWork event handler, this way you can simply use the BackgroundWorkers ReportProgress method to update the dialog.
Any suggestions or criticisms, feel free to comment or contact me directly! Always keen to learn and improve 🙂