解决这个问题会给你留下几种可能性之一......
- 不显示进度
- 使用前期成本进行计算(如 Windows)
- 在计算成本的同时执行操作
如果速度如此重要并且您期望大型目录树,我会倾向于这些选项中的最后一个。我已经在链接的问题上添加了一个答案,快速获取特定路径中的所有文件和目录,这展示了一种比您当前使用的更快的计算文件和大小的方法。要将其组合到选项 #3 的多线程代码中,可以执行以下操作...
static void Main()
{
const string directory = @"C:\Program Files";
// Create an enumeration of the files we will want to process that simply accumulates these values...
long total = 0;
var fcounter = new CSharpTest.Net.IO.FindFile(directory, "*", true, true, true);
fcounter.RaiseOnAccessDenied = false;
fcounter.FileFound +=
(o, e) =>
{
if (!e.IsDirectory)
{
Interlocked.Increment(ref total);
}
};
// Start a high-priority thread to perform the accumulation
Thread t = new Thread(fcounter.Find)
{
IsBackground = true,
Priority = ThreadPriority.AboveNormal,
Name = "file enum"
};
t.Start();
// Allow the accumulator thread to get a head-start on us
do { Thread.Sleep(100); }
while (total < 100 && t.IsAlive);
// Now we can process the files normally and update a percentage
long count = 0, percentage = 0;
var task = new CSharpTest.Net.IO.FindFile(directory, "*", true, true, true);
task.RaiseOnAccessDenied = false;
task.FileFound +=
(o, e) =>
{
if (!e.IsDirectory)
{
ProcessFile(e.FullPath);
// Update the percentage complete...
long progress = ++count * 100 / Interlocked.Read(ref total);
if (progress > percentage && progress <= 100)
{
percentage = progress;
Console.WriteLine("{0}% complete.", percentage);
}
}
};
task.Find();
}
FindFile 类的实现可以在FindFile.cs中找到。
根据您的文件处理任务的成本(上面的 ProcessFile 函数),您应该看到大量文件的进度非常干净。如果您的文件处理速度非常快,您可能希望增加枚举开始和处理开始之间的延迟。
event 参数的类型是FindFile.FileFoundEventArgs并且是一个可变类,因此请确保不要保留对 event 参数的引用,因为它的值会发生变化。
理想情况下,您将希望添加错误处理以及可能中止两个枚举的能力。可以通过在事件参数上设置“CancelEnumeration”来中止枚举。