5

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

7 回答 7

8

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

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

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

于 2009-01-27T18:05:59.883 回答
2

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

于 2009-01-27T16:36:19.703 回答
1

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

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

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

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

于 2009-01-27T16:36:30.310 回答
1

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

于 2009-01-28T14:54:05.103 回答
0

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

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

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

于 2009-01-27T16:59:57.270 回答
0

您可以创建具有递增最大值和值属性的进度条。如果您的 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

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

于 2009-01-27T17:23:23.260 回答
0

我使用了 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-12-28T04:20:42.370 回答