解决这个问题会给你留下几种可能性之一......
- 不显示进度
- 使用预付费用进行计算(如 Windows)
- 执行操作同时计算成本
如果速度很重要,并且您期望大型目录树,我会倾向于这些选项中的最后一个。我在链接的问题Get all files and directories in specific path fast 上添加了一个答案,它演示了一种比您当前使用的更快的计算文件和大小的方法。要将其组合到选项 #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 class 的实现可以在FindFile.cs 找到。
根据您的文件处理任务的成本(上面的 ProcessFile 函数),您应该会看到处理大量文件的进度非常清晰。如果您的文件处理速度非常快,您可能希望增加枚举开始和处理开始之间的延迟。
事件参数的类型为FindFile.FileFoundEventArgs,并且是一个可变类,因此请确保不要保留对事件参数的引用,因为它的值会发生变化。
理想情况下,您会想要添加错误处理,并且可能想要中止两个枚举。可以通过在事件参数上设置“CancelEnumeration”来中止枚举。