使用后台工作程序 - 更新ProgressBar以了解递归方法的进度

时间:2009-08-26 13:44:04

标签: c# winforms progress-bar backgroundworker

下面是一个我希望发送给后台工作者的方法,但是我正在努力根据创建方法的方式来完成它。尽管如此,它不会返回任何正常的内容,但每次调用时都需要一个directoryInfo对象。

    private void getSizeForTargetDirectory(DirectoryInfo dtar)
    { 
        // generate a collection of objects. files comes first and then directories.

        foreach (Object item in collection )
        {
            if (item == file)
            {
               track the size of the files as you encounter.
            }
            else if (item == directory)
            {
                // found a new directory, recall the method. !!!
            }
        }
    }

这是我第一次使用后台工作人员,所以我有点陷入困境,我尝试通过这里找到的帮助来实现一些东西,但是当我意识到我的方法是递归的时候卡住了。

How do I display progress during a busy loop?

我实现了一个doWork事件处理程序方法但注意到如果我有更多的文件和文件夹要在较低的子级别处理,我需要以某种方式回想一下该方法。

我有一个简单的按钮单击事件处理程序,当当前所选节点是目录时,它调用我的'getSizeForTargetDirectory()'方法。

 private void retrieveInfoButton_Click(object sender, EventArgs e)
    {
        // check to see if the path is valid
        // reset the labels and textfields.
        string fullPath = treeDrives.SelectedNode.FullPath;
        string sNodesName = treeDrives.SelectedNode.Text;

        if (directory) // Enter here if its a directory.
        {
            string parentPath = treeDrives.SelectedNode.Parent.FullPath;
            DirectoryInfo[] dirArray = populateFoldersArray(parentPath);

            for (int i = 0; i < dirArray.Length; i++)
            {
                if (dirArray[i].Name == sNodesName)
                {
                    getSizeForTargetDirectory(dirArray[i]);

                    // do work !

希望这能解释我想要做什么以及我是如何做到的。问题是当我尝试发布的大部分工作来自递归方法时,我如何使用后台工作者类的报告进度功能。

通过早期测试,我注意到我的getSize方法经过一些调整后非常高效,并且报告当前提供的文件夹的大小信息非常快,但是我再次使用相当强大的开发机器,所以对于所有用户来说可能并非如此。

感谢阅读,希望有人可以帮助!!!

3 个答案:

答案 0 :(得分:3)

我认为在DirectoryDirectoryInfo上使用内置方法使用递归搜索选项获取所有目录或文件要简单得多:

public partial class Form1 : Form
{
    private Action<float> updateProgMethod;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        updateProgMethod = UpdateProgress;
    }

    private void GetDirectorySizeAsync(string path)
    {
        backgroundWorker.RunWorkerAsync(path);
    }

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        DirectoryInfo di = new DirectoryInfo((string)e.Argument);
        di.GetTotalSize(ProgressCallback);
    }

    // Takes callbacks from the GetTotalSize() method
    private void ProgressCallback(float p)
    {
        // Invokes update progress bar on GUI thread:
        this.BeginInvoke(updateProgMethod, new object[] { p });
    }

    // Actually updates the progress bar:
    private void UpdateProgress(float p)
    {
        progressBar.Value = (int)(p * (progressBar.Maximum - progressBar.Minimum)) + progressBar.Minimum;
    }
}

public static class IOExtensions
{
    public static long GetTotalSize(this DirectoryInfo directory, Action<float> progressCallback)
    {
        FileInfo[] files = directory.GetFiles("*.*", SearchOption.AllDirectories);
        long sum = 0;
        int countDown = 0;
        for (int i = 0; i < files.Length; i++)
        {
            sum += files[i].Length;
            countDown--;
            if (progressCallback != null && countDown <= 0)
            {
                countDown = 100;
                progressCallback((float)i / files.Length);
            }
        }
        return sum;
    }
}

如果不先知道文件或文件夹的数量就很难猜测进度!

编辑:我对代码进行了一些改进。

答案 1 :(得分:2)

如果在调用方法时,您不知道该方法需要多长时间或涉及多少个离散步骤,那么在执行该方法时无法显示进度条

在我看来,进度条的目的不是提供有关何时完成任务的可靠信息。相反,目的是让用户不要害怕并取消整个操作,因为他们认为你的程序已被锁定并且根本没有做任何事情。

由于您正在遍历目录和子目录,因此这里更简单的方法可能是在Label中显示当前目录。这将使用户感觉到事情正在发生,如果目录全部按字母顺序排列,他们甚至可以自己测量操作的整体进度。

答案 2 :(得分:0)

我会报告你已经走了多远,因为在你到达那里之前你不知道目标。我会在每次调用时执行一次。也许到目前为止看到的文件数量和目录数量。