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;
}
}