65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 BackgroundWorker 将图标转换为图像

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (5投票s)

2009年1月21日

CPOL

2分钟阅读

viewsIcon

31565

downloadIcon

484

使用后台工作线程执行耗时任务

引言

本文演示了如何使用后台工作线程来执行耗时任务。

背景

我喜欢创建软件,为此我需要一些用于按钮等的图像。互联网上有很多可以下载的图像,但不幸的是,许多图像都是图标格式(.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; 
}

就是这样了。它应该很容易实现。

关注点

我花了很长时间才最终理解这个过程。实际上,大部分信息来自帮助文档,但缺少一些要点,因此实现起来并不像应该那么容易。

© . All rights reserved.