代码之家  ›  专栏  ›  技术社区  ›  Brian

扫描硬盘时的进度条

  •  5
  • Brian  · 技术社区  · 17 年前

    所以,我要做一个简单的扫描来获取硬盘上所有文件夹的列表(C:\windows和C:\windows\system32被认为是单独的条目)。如果我想为这个1-2分钟的任务提供进度条,我该怎么做?也就是说,我知道如何创建进度条,但不知道如何确定为它完成了多少工作。

    编辑:请注意,执行预扫描不是一个解决方案,因为此扫描只获取文件夹列表,而预扫描所需的时间也一样长。

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

    我发现的一种机制可能不是100%可靠,但比我的扫描速度快得多,那就是将“dir/s/ab/b”传输到我的程序,并计算newline的实例。Dir做了一些比我的程序扫描高清效果更好的魔术,但我不知道那是什么魔术。

    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 回复  |  直到 14 年前
        1
  •  0
  •   Michael Todd    17 年前

    如果您不能重复使用目录结构,因为这需要首先执行任务,那么您可以做的最好的事情就是猜测有多少个文件夹。说真的。

    也许您可以使用基于过去历史的算法(例如,上次我这样做时,有10个顶级目录,总共有150个目录,因此一个好的猜测是当前顶级目录数量的15倍)。

    告诉用户一些事情的另一种方法是使用倒计时计时器(不知道确切的时间)。即使你已经猜到某件事情会比实际需要的时间更长(比如说,当它实际上是一个3分钟的任务时需要5分钟),至少用户大致知道它需要多长时间。他们会更高兴,当它完成得比他们被告知的快。当然,唯一令人不安的是,如果你在另一方面猜错了,也就是说,如果某件事情花费的时间比你想象的要长。然后他们坐在那里等着(在他们的头脑中)应该已经完成的事情。

        2
  •  8
  •   Welbog    17 年前

    如果你需要建立一个进度条,而你又不能抽出时间来收集准确的信息,那么你就不能建立一个完美的进度条。考虑到这个假设,您仍然可以创建一个不完全不准确的进度条。

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

    进度条上的每个百分比并不代表算法完成的工作量相同,但是考虑到你的缺点,我怀疑你能做得更好。

        3
  •  2
  •   Jacek Ławrynowicz    17 年前

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

        4
  •  1
  •   Mitchel Sellers    17 年前

    你可以用几种方法来做……一个简单的过程,可能不是100%准确。

    在开始之前,获取文件计数,然后使用该计数计算完成百分比,在处理完x个文件后更新进度。假设存在查找的性能成本。也许只需要得到根目录的计数,当您遍历时更新进度。

    另一种选择可能是简单地记录“上次运行”详细信息的计数,并使用它来计算百分比,同样,不一定100%准确,而是一个选项。

    我想还有其他一些事情需要考虑,就是简单地向用户显示一个“进行中”对话框,而不是试图获得一个百分比。否则,可能只显示当前工作目录,显示您正在取得进展。

        5
  •  1
  •   Brian    17 年前

    我试着抓住 dir/ad/b/s c:/ “计算行数。这很快。它足够可信,可以在ProgressBar中使用,但不足以作为目录列表使用。

        6
  •  0
  •   Leon Tayson    17 年前

    您可以使用递增的最大值属性创建进度条。如果您的最大属性最初设置为100,则在计时器的勾号事件中,将最大值和最大值都增加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
    

    您可以对初始最大值进行实验,以使进度条移动更平滑。

        7
  •  0
  •   Tim Cooper    14 年前

    我用了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); }
    

    它运行得很平稳,而且很便宜。我还为用户提供了一个准确的进度条选项,我首先计算dirs的总数,这可能很昂贵。