2

下面是一种我想发送给后台工作人员的方法,但我正在努力根据我的方法的创建方式来实现它。如您所知,它不会返回任何可以的内容,但每次调用它时都需要一个 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. !!!
            }
        }
    }

这是我第一次使用后台工作人员,所以我有点卡住了,由于在这里找到的帮助,我尝试实现一些东西,但是当我意识到我的方法是递归的时就卡住了。

如何在繁忙的循环中显示进度?

我实现了一个 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 方法在经过一些调整后非常有效,并且非常快速地报告了当前提供的文件夹的大小信息,但是我再次使用了功能强大的开发机器,因此这可能不适用于所有用户。

感谢阅读,希望有人能帮忙!!!

4

3 回答 3

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

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

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

于 2009-08-26T13:54:09.477 回答
2

如果在调用方法时,您不知道该方法将花费多长时间或将涉及多少离散步骤,则无法在方法执行时显示进度条。

在我看来,进度条的目的不是提供有关何时完成任务的可靠信息。相反,目的是防止用户因为认为您的程序已锁定并且根本没有做任何事情而惊慌失措并取消整个操作。

由于您正在遍历目录和子目录,因此这里更简单的方法可能是仅在标签中显示当前目录。这会给用户一种事情正在发生的轻松感觉,如果目录都按字母顺序排列,他们甚至可以自己衡量操作的整体进度。

于 2009-08-26T13:54:35.140 回答
0

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

于 2009-08-26T14:01:34.400 回答