【问题标题】:ProgressBar when Scanning a Hard Drive扫描硬盘时的进度条
【发布时间】:2009-01-27 16:32:17
【问题描述】:

所以,我正在做一个简单的扫描以获取硬盘驱动器上所有文件夹的列表(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:\\");
    }
}

【问题讨论】:

    标签: file progress-bar directory


    【解决方案1】:

    如果您需要制作进度条,但又抽不出时间来收集准确的信息,那么您将无法制作出完美的进度条。考虑到这一假设,您仍然可以制作一个并非完全不准确的进度条。

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

    进度条上的每个 % 不会代表算法完成的相同数量的工作,但考虑到您的限制,我怀疑您可以做得更好。

    【讨论】:

    • 我怀疑这样的事情会是我能做的最好的事情:/
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      您可以通过几种方式做到这一点....一个可能不是 100% 准确的简单过程。

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

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

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

      【讨论】:

      • 正如我所说,所有此扫描所做的只是获取文件夹列表。任何像你提出的解决方案都需要我的扫描时间。
      • 假设您使用的是 .NET 之类的东西,您可能可以使用 DirectoryInfo.GetDirectories(String, SearchOption) 之类的东西,然后使用返回集合的计数。所以它应该接近即时......
      • Rich:不,因为我正在获取所有目录。如果您的解决方案有效,我会使用 THAT 功能进行扫描。
      • @Brian - 我认为这引出了你当时在做什么的问题。创建文件夹列表不应该花费那么长时间来完成。我有一个系统,可以解析 1000 个文件夹中的 15,000 个文件,对每个文件夹执行逻辑和磁盘写入,并且它在 15 秒内运行。
      • @Brian - 你能添加一个代码示例,或者告诉我们你在代码中做了什么吗?
      【解决方案4】:

      我尝试获取“dir/ad/b/s c:/”的标准输出并计算行数。这是相当快的。它对于在进度条中使用来说足够可信,但对于用作目录列表来说不够可信。

      【讨论】:

        【解决方案5】:

        如果您不能递归目录结构,因为这将花费一开始执行任务的时间,那么您能做的最好的事情就是猜测有多少文件夹。严重地。

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

        另一种告诉用户某些事情需要一段时间(不知道确切的时间)的方法是使用倒数计时器。即使您已经猜到某事会比实际花费更长的时间(比如说 5 分钟,而实际上是 3 分钟的任务),至少用户知道大概需要多长时间。当它完成得比他们被告知的要快时,他们会更快乐。当然,唯一的遗憾是,如果你在另一边猜错了,即,如果某件事花费的时间比你想象的要长。然后他们就坐在那里等待完成(在他们看来)应该已经完成​​的事情。

        【讨论】:

        • 如果您知道驱动器的大小(以字节为单位),您就不能计算每个扫描目录的字节数吗??
        【解决方案6】:

        您可以创建具有递增最大值和值属性的进度条。如果您的 Maximum 属性最初设置为 100,则在 Timer's 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
        

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

        【讨论】:

          【解决方案7】:

          我使用了 Catchwa 的方法。我将进度范围设置为 14000,因为我系统上的操作系统有那么多目录。当我找到一个空目录时,我将分数加权量添加到进度条。数量基于深度并随范围标准化。在每次子树遍历中,您最终都会得到一个空目录,并且目录中所有空子目录的权重构成该目录的权重,但会分成块。当我找到一个非空目录时,我将子目录的数量存储在地图中。我得到了,使用 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); }
          

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

          【讨论】:

            猜你喜欢
            • 2010-11-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-19
            • 1970-01-01
            相关资源
            最近更新 更多