I’ve been working on an application the past few days that iterates through directories and processes files within those directories. I was looking for a good way to keep the user informed of progress, and I decided that using System.ComponentModel.BackgroundWorker was my best solution.
Here’s some relevant code for how I used UserState to keep the user updated of the progress:
namespace BackgroundWorkerSample
{
public partial class Main : Form
{
#region Form Callbacks
private void btnCancel_Click(object sender, EventArgs e)
{
// Let the user know the cancel is processing
btnCancel.Text = "Cancelling...";
btnCancel.Enabled = false;
// Ask the background worker to cancel its process
if ((null != _FileProcessingWorker) && (_FileProcessingWorker.IsBusy))
{
_FileProcessingWorker.CancelAsync();
}
}
private void btnProcess_Click(object sender, EventArgs e)
{
// Set up the background worker
_FileProcessingWorker = new BackgroundWorker();
_FileProcessingWorker.WorkerReportsProgress = true;
_FileProcessingWorker.WorkerSupportsCancellation = true;
// Add the events needed for the background worker
_FileProcessingWorker.DoWork += new DoWorkEventHandler(_FileProcessingWorker_DoWork);
_FileProcessingWorker.ProgressChanged += new ProgressChangedEventHandler(_FileProcessingWorker_ProgressChanged);
_FileProcessingWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_FileProcessingWorker_RunWorkerCompleted);
// Get the directory to process
string BasePath = lblDirectoryName.Text;
DirectoryInfo MyDirectory = new DirectoryInfo(BasePath);
DirectoryInfo[] MySubDirectories = MyDirectory.GetDirectories();
// Collect statistics for the progress bar
int SubDirectoryCount = MySubDirectories.GetLength(0);
MyProgressBar.Minimum = 0;
MyProgressBar.Step = 1;
MyProgressBar.Maximum = SubDirectoryCount;
MyProgressBar.Value = MyProgressBar.Minimum;
_LastCounter = 0;
// Instantiate the background worker and pass the file list
_FileProcessingWorker.RunWorkerAsync(MySubDirectories);
}
#endregion
#region File processing methods and events
private void _FileProcessingWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Cast the EventArgs to the expected type
DirectoryInfo[] MySubDirectories = (DirectoryInfo[])e.Argument;
// Loop through the subdirectories
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
{
DirectoryInfo MySubDirectory = MySubDirectories[i];
// Keep track of the current directory
string CurrentDirectory = "Current Directory: " + MySubDirectory.Name;
// Loop through the matching files
foreach (FileInfo MyFile in MySubDirectory.GetFiles("*.txt"))
{
// See if the user has requested cancellation
if (_FileProcessingWorker.CancellationPending)
{
e.Cancel = true;
return;
}
// Keep track of the current file
string CurrentFile = "Current File: " + MyFile.Name;
// Create an object to report the status via UserState
string[] CurrentStatus = new string[2];
CurrentStatus[0] = CurrentDirectory;
CurrentStatus[1] = CurrentFile;
// Raise the ProgressChanged event to allow reporting of status
_FileProcessingWorker.ReportProgress(i, CurrentStatus);
// Do the needed processing on the file
Thread.Sleep(500);
}
}
}
private void _FileProcessingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Update the progress bar and status labels when the background worker reports progress
// Cast the EventArgs to the expected type
if (typeof(string[]) == e.UserState.GetType())
{
string[] StatusMsg = (string[])e.UserState;
if (2 == StatusMsg.GetLength(0))
{
// Update the status labels
lblCurrentDirectory.Text = StatusMsg[0];
lblStatus.Text = StatusMsg[1];
}
}
// See if the percentage completion needs to be updated
if (e.ProgressPercentage > _LastCounter)
{
_LastCounter = e.ProgressPercentage;
// Increment the progress bar
MyProgressBar.PerformStep();
}
}
private void _FileProcessingWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Keep the display of the last directory and file processed
lblCurrentDirectory.Text = lblCurrentDirectory.Text.Replace("Current", "Last");
lblStatus.Text = lblStatus.Text.Replace("Current", "Last");
}
#endregion
}
}
You can download a complete project here.

Excellent sample. Thanks for posting this. It was very helpful.
Comment by Foxhunter — March 3, 2010 @ 8:14 am
I think this works on a single main form. My requirement is different: The file name being read must be viewed from a Childform.showDialog(). Can this be done?
Comment by Benj — April 1, 2011 @ 2:19 am