
Introduction
This article is an extended version of another article that I found very interesting, named BackgroundWorker Threads and Supporting Cancel, written by Andrew D. Weiss.
This article explains how a BackgroundWorker thread is run asynchronously to scan image dimensions. The user has the option to select a folder or select some specific images. After inserting the image names to a ListView, a collection object is passed to the BackgroundWorker that scans each image and reports the progress back and displays it on a ProgressBar.
Using the code
When photos are added, they are stored in an object named PhotoCollection, that inherits from List<Photo>. Each photo has a FileInfo instance and some added properties. The PhotoCollection can be exported into an XML file, and imported back from an XML file, using the class XmlParser.
This software can be extended further into a resizing program, renamer, organizer, or whatever you would want to do to a collection of photos. The BackgroundWorker could also pre-generate thumbnails, and the ListView could be replaced with a “Large Icon” view like you can see in Windows XP or later.
BackgroundWorker
The method UpdateListView_HeavyProcess() starts the thread and feeds it its working argument. The method worker_DoWork() will run the heavy process, and each time trd.ReportProgress() is called inside worker_DoWork(), the method worker_ProgressChanged() is invoked which is allowed to update the GUI components. When the thread has completed its work, the method worker_RunWorkerCompleted() is called which casts the results back to PhotoCollection.
private void UpdateListView_HeavyProcess()
{
if (!worker.IsBusy)
{
prbProgress.Minimum = 0;
prbProgress.Maximum = photos.Count;
prbProgress.Value = 0;
prbProgress.Step = 1;
prbProgress.Enabled = true;
worker.RunWorkerAsync(photos);
}
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker trd = sender as BackgroundWorker;
PhotoCollection col = (PhotoCollection)e.Argument;
Image img;
for (int i = 0; i < col.Count; i++)
{
if (col[i].PixelHeight == 0 && col[i].PixelWidth == 0)
{
img = Image.FromFile(col[i].FullName);
col[i].PixelWidth = (int)img.PhysicalDimension.Width;
col[i].PixelHeight = (int)img.PhysicalDimension.Height;
}
trd.ReportProgress(i, col[i].Dimention);
if (trd.CancellationPending)
{
e.Cancel = true;
e.Result = col;
trd.ReportProgress(-1);
return;
}
}
e.Result = col;
trd.ReportProgress(-1);
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
photos = (PhotoCollection)e.Result;
this.UpdateListView(true);
prbProgress.Minimum = 0;
prbProgress.Value = 0;
prbProgress.Enabled = false;
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
this.Text = "<" + photos[e.ProgressPercentage].Name +
"> " + ProgramName;
prbProgress.PerformStep();
lsvFiles.Items[e.ProgressPercentage].SubItems[2].Text = e.UserState.ToString();
}
catch
{
this.Text = ProgramName;
}
}
It all started with enthusiasm for creating mods for Quake 2 many many years ago. After graduation from the technical college, I moved to Denmark and got a Bs. degree in software engineering from Aalborg University.