使用 BackgroundWorker 将图标转换为图像
使用后台工作线程执行耗时任务
引言
本文演示了如何使用后台工作线程来执行耗时任务。
背景
我喜欢创建软件,为此我需要一些用于按钮等的图像。互联网上有很多可以下载的图像,但不幸的是,许多图像都是图标格式(.ico、.icl 等),在使用前必须进行转换。你可以使用许多图像编辑器,如 PhotoShop、Gimp、Axialis 等,但你必须逐个转换图像。由于我有点懒,当然不喜欢这样,所以我创建了一个应用程序来自动化这个过程。转换功能非常耗时,因此会导致用户界面 (UI) 无响应。为了解决这个问题,该功能必须在后台线程中执行。
Using the Code
为了转换图标,我使用了来自 这篇文章 的 iconlib 库。[^]
以下 struct
用于向后台工作线程传递参数。你需要两个这样的结构体,一个用于传递给后台工作线程,另一个用于更新 UI。
public struct PassedObject //for passing to background worker
{
public List<string> fileListing;
public string initDirectory;
public PassedObject(List<string> listFilenya, string initDirnya)
{
fileListing = listFilenya;
initDirectory = initDirnya;
}
}
public struct ItemToReport //for passing from background worker
{
public string strToReport ;
public int id;
public ItemToReport(string reportString, int ID)
{
strToReport = reportString;
id = ID;
}
}
以下函数在后台执行,转换图标。请注意,此代码中发生的任何异常都很难调试。(我使用的是 Express 版本。)
private void convertIcon(BackgroundWorker worker, DoWorkEventArgs e)
{
PassedObject objectToPass = (PassedObject)e.Argument; //perform unboxing
//initial folder to create new folders of converted image
string initDirectory = objectToPass.initDirectory ;
///hold list of files
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; //reset icon counter, prevent overflow at progressbar
worker.ReportProgress(0, pesan); //report : processing----
...
}
}
调用后台函数并开始执行后台线程的函数是
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
convertIcon(worker, e);
}
当后台函数想要在主线程上更新 UI 时,会调用此代码。在我的应用程序中,它用于更新 ProgressBar
。为了允许更新 UI,你需要将 workerReportProgress
设置为 true
。
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ItemToReport report = (ItemToReport)e.UserState; //perform unboxing message
switch (report.id )
{
case 0:
rtbReport.AppendText(report.strToReport);
break;
...
}
}
当后台工作线程完成其工作时,会调用以下函数。
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnConvert.Enabled = true;
}
就是这样了。它应该很容易实现。
关注点
我花了很长时间才最终理解这个过程。实际上,大部分信息来自帮助文档,但缺少一些要点,因此实现起来并不像应该那么容易。