Tek Eye

C# BackgroundWorker with Progress Bar

When developing software not only is the program's main purpose important, i.e. what task the program performs, there are other aspects to consider. These other aspects of a computer program include things like usability, security and maintainability. This article looks at an important part of usability, specifically how the interface for a C# program can keep the user updated and the User Interface (UI) responsive when running intensive tasks. In this tutorial this is done with the BackgroundWorker and ProgressBar .NET Framework classes.

The Importance of Program Responsiveness

In terms of usability the program's UI should be informative, responsive and reflect the status of the program and the data it is processing. A program should keep the user updated on what it is doing. One of the annoying problems of badly written software is when it fails to provide useful feedback and fails to respond to users actions. In such cases the user may force the program to close because it gives the impression it has stopped working.

Modern computers are extremely powerful and often come with multiple processing cores that can run many threads. It is easy for a modern PC to support multithreaded programs. Therefore, there is no excuse for software to not be responsive and user friendly. However, even popular operating systems and programs still fail to provide a good user experience. Part of the problem lies with the software writers. Whilst it is easy for a PC to run multithreaded programs, some developers are not inclined to develop them because they can be harder to debug if programming errors are made. However, for those developing Windows applications on the .NET Framework there are classes available that an application can use to run multiple threads.

BackgroundWorker Class Runs Code on Another Thread

A normal Windows Forms (WinForms) application has one thread. The main UI thread, which not only runs the main program code it also services all the screen interface elements. If intensive code, such as complex calculations, or slow code, such as heavy Internet access, runs in the main program code, then the UI can become unresponsive.

The BackgroundWorker is available from the Visual Studio Toolbox (although BackgroundWorker can be used programmatically). BackgroundWorker is straightforward to use, there are a couple of examples at the Microsoft BackgroundWorker documentation. However, it is often misused, with a few programmers thinking it doesn't work. Usually because they don't really understand its correct operation.

Using the BackgroundWorker

Any intensive or slow code can be run by the BackgroundWorker off the DoWork event. However, the slow or intensive code must be self-contained and cannot access UI elements or other methods on the UI thread. To support this self-containment and communicate with the UI thread (to update the interface) the ProgressChanged event can be used. Finally, once the task called by the DoWork event has completed, the BackgroundWorker can fire another event, RunWorkerCompleted, to let the main program know the task has finished. Finally, if necessary, the background task can be cancelled using BackgroundWorker's CancelAsync method.

In this example the BackgroundWorker is going to count the English letter characters in a text file. This task has been chosen to illustrate the workings of a BackgroundWorker, a simple example of processing that can be moved to a BackgroundWorker. Though unless it is processing a hundred megabytes plus file, it still runs very fast on a modern computer.

(Why count the English letters in a file? Counting letter frequency is a technique used in forensic and cryptography applications. Here it is juts used as a file processing example.)

BackgroundWorker with ProgressBar Example Code

As shown in the image at the start, the simple app allows a text file to be chosen (using a FileOpenDialog), and then analysed, with percentage progress shown, and messages added to a list (ListBox). A BackgroundWorker is available from the Toolbox and can be dropped onto a WinForm. Note, the code for the actual WinForm construction is not shown as it standard stuff. Download the Visual Studio solution in the backgroundworker-demo.zip file to have a look at all the source. Here is the main code:

Running the BackgrounderWorker Example

Unless you have a tens of megabytes plus text file, the processing will be very quick. (If you want some big text files an Internet search will reveal several sources). Due to the fast processing the ProgressBar update lags behind the file processing, the UI is slow to update (to improve that aspect the number of characters processed before calling ReportProgress can be increased). To see the processing and ProgressBar update in action on smaller files slow down the processing by getting the background thread to wait a little longer:

Once the code for this BackgroundWorker example has been examined it will be seen that it is a useful template for other intensive or slow processing tasks that a C# program will need to do. Get code in the backgroundworker-demo.zip file or from GitHub.