Introduction
This article is an example of using a background worker thread to execute a time consuming task.
Background
I like creating software and for this I need some images for buttons, etc. There are many images you can find for downloading from the internet, but unfortunately, many are in icon format (.ico, .icl, etc) and must be converted before use. You can use many image editors such as PhotoShop, Gimp, Axialis, etc., but you must convert the images one by one. Being kind of lazy, of course I don't like that, so I created an application to automate the process. The function for converting is time consuming, however, so it makes user interface (UI) unresponsive. To resolve that problem, the function must execute in a background thread.
Using the Code
To convert icons, I use the iconlib library from this article. [^]
The following struct
is used for passing an argument to the background worker. You need two of these, one for passing to background worker and one for updating the UI.
public struct PassedObject
{
public List<string> fileListing;
public string initDirectory;
public PassedObject(List<string> listFilenya, string initDirnya)
{
fileListing = listFilenya;
initDirectory = initDirnya;
}
}
public struct ItemToReport
{
public string strToReport ;
public int id;
public ItemToReport(string reportString, int ID)
{
strToReport = reportString;
id = ID;
}
}
The following function executes in background, converting the icons. Be careful, because any exception that occurs in this code is hard to debug. (I'm using the Express Edition.)
private void convertIcon(BackgroundWorker worker, DoWorkEventArgs e)
{
PassedObject objectToPass = (PassedObject)e.Argument;
string initDirectory = objectToPass.initDirectory ;
List<string> fList = objectToPass.fileListing ;
...
foreach (string item in fList )
{
FileInfo iconFile = new FileInfo(item);
ItemToReport pesan = new ItemToReport("processing " + iconFile.Name + "...\n", 0);
curIconProg = 0;
worker.ReportProgress(0, pesan);
...
}
}
The function that calls the background function and begins execution of the background thread is
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
convertIcon(worker, e);
}
This code is called when the background function wants to update the UI on the main thread. In my application, it is used for updating the ProgressBar
. To allow the UI to be updated, you need to set workerReportProgress
to true
.
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ItemToReport report = (ItemToReport)e.UserState;
switch (report.id )
{
case 0:
rtbReport.AppendText(report.strToReport);
break;
...
}
}
The following function is called when the background worker has complete its work.
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnConvert.Enabled = true;
}
That's all there is to it. It should be easy to implement.
Points of Interest
It took me a long time to finally understand this process. Actually, most of the information comes from help, but some points are missing so it's not as easy to implement as it should be.