扫描硬盘时的ProgressBar

时间:2009-01-27 16:32:18

标签: file progress-bar directory

所以,我正在进行一次简单的扫描,以获取硬盘驱动器上所有文件夹的列表(c:\ windows和c:\ windows \ system32被视为单独的条目)。如果我想为这1-2分钟的任务提供进度条,我该怎么办呢?也就是说,我知道如何制作进度条,但不知道如何确定完成了多少工作。

编辑:请注意,执行预扫描不是一种解决方案,因为此扫描只获取文件夹列表,而预扫描只需要一段时间。

代码示例如下。在我的系统上运行干净需要不到2分钟,但由于磁盘访问缓存,第二次运行时间不到10秒。我已经创建了基于堆栈而不是基于递归的变体。

我发现的一种机制可能不是100%可靠,但比我的扫描快得多,将“dir / s / ab / b”传送到我的程序并计算换行的实例。 Dir做了某种魔术,比我的程序扫描HD更好,但我不知道那是什么魔法。

class Program
{
    static void recurse(string pos)
    {
        DirectoryInfo f = new DirectoryInfo(pos);
        try
        {
            foreach (DirectoryInfo x in f.GetDirectories("*"))
            {
                recurse(x.FullName);
            }
        } catch (Exception) {}
    }
    static void Main(string[] args)
    {
        recurse("c:\\");
    }
}

7 个答案:

答案 0 :(得分:8)

如果您需要制作一个进度条而且无法节省收集准确信息所需的时间,那么您将无法创建完美的进度条。考虑到这一假设,您仍然可以创建一个不完全不准确的进度条。

例如,您根据当前目录中的子目录数创建一个细分进度条的函数。因此,如果您的根目录有10个子目录,请将10%的进度条分配给每个目录。然后,进入第一个子目录并计算其子目录。如果它有5,则将前10%的进度条的20%分配给每个进度条(占总进度条的2%)。像这样继续,直到你到达一个没有子目录的目录,在那里进行处理并增加进度条它代表的任何小数量。

进度条上的每个%都不代表算法所做的相同工作量,但考虑到你的约束,我怀疑你能做得更好。

答案 1 :(得分:2)

只是不要使用它。尝试更合适的东西,如旋转动画或Kitts样式栏:http://en.wikipedia.org/wiki/KITT

答案 2 :(得分:1)

你可以通过几种方式实现......一个可能不是100%准确的简单过程。

在开始之前,获取文件计数,然后在处理X文件更新进度后使用它来计算完成百分比。当然,查找的性能成本。也许只需获取根目录的数量,并在遍历时更新进度。

另一种选择可能是简单地记录“最后一次运行”细节的计数,并使用它来计算百分比,再次,不一定是100%准确,但是一个选项。

我想其他一些想法是简单地向用户显示“进行中”对话框,甚至不尝试获得百分比。否则,可能只显示当前的工作目录,表明您正在取得进展。

答案 3 :(得分:1)

我尝试抓住“dir/ad/b/s c:/”的stdoutput并计算行数。这很快。它足够值得信赖,可以在进度条中使用,但不足以作为目录列表使用。

答案 4 :(得分:0)

如果您无法递归目录结构,因为只要首先执行任务就需要这样做,您可以做的最好的事情是猜测有多少个文件夹。认真。

也许您可以使用基于过去历史的算法(例如,我最后一次执行此操作时,当有10个顶级目录时总共有150个目录,因此一个好的猜测将是当前顶级目录的15倍级别目录)。

告诉用户某事的另一种方法是花一段时间(不知道究竟有多长时间)使用倒数计时器。即使你已经猜到某些东西需要的时间比它实际上要长(比如5分钟,这真是一个3分钟的任务),至少用户大致知道需要多长时间。当它完成得比它们被告知的要快时,它们会更快乐。当然,唯一令人失望的是,如果你在另一方面猜错了,也就是说,如果事情需要的时间比你想象的要长。然后他们坐在那里等待完成的事情(在他们看来)应该已经完成​​了。

答案 5 :(得分:0)

您可以使用递增最大值和最大值来创建进度条。价值属性。如果您的最大属性最初设置为100,则在计时器的Tick事件中,增加最大值和最大值。例如,值为1,因此您将在下面列出值...

         Maximum    Value 
Tick1:    101          1   - 1% 
Tick2:    102          2   - 2%
Tick3:    103          3   - 3% 
TickN:    100+n        n 
Finish    100+n      100+n - 100%  --> force to fill the progress bar

您可以尝试初始最大值,以使进度条移动更顺畅。

答案 6 :(得分:0)

我使用了Catchwa的方法。我将进度范围设置为14000,因为我系统上的操作系统有很多目录。当我找到一个空目录时,我将小数加权数量添加到进度条。数量基于深度并按范围标准化。在每个子树遍历中,你最终得到一个空的目录,并且dir中所有空子目录的权重包括dir的权重,但是分成块。当我找到一个非空目录时,我在地图中存储了子目录的数量。我得到了,使用Qt:

emit findProgressBar_setRange(14000); ... if (dir.size()) { m_dirsAtDepth[++m_depth] = dir.size(); } else { qreal product = 1.00; for (int i = 1; i <= m_depth; ++i) { product *= m_dirsAtDepth[i]; } int x = qRound((1.00 / product) * 14000); emit findProgressBar_addValue(x); }

它运行得非常顺畅而且价格便宜。我还为用户提供了一个准确的进度条选项,我首先计算了目标总数,这可能很昂贵。