我开发了一个应用程序,可以扫描基本上所有地方的文件或文件列表。 当我扫描像 10 000 个文件和子文件这样的小文件夹时,没有问题。但是,当我扫描包含超过 100 000 个项目的整个用户文件夹时,我的处理器负担非常重。它占用了我处理器大约 40% 的电量。
有没有办法优化此代码,使其使用更少的 CPU?
procedure GetAllSubFolders(sPath: String);
var
Path: String;
Rec: TSearchRec;
begin
try
Path := IncludeTrailingBackslash(sPath);
if FindFirst(Path + '*.*', faAnyFile, Rec) = 0 then
try
repeat
Application.ProcessMessages;
if (Rec.Name <> '.') and (Rec.Name <> '..') then
begin
if (ExtractFileExt(Path + Rec.Name) <> '') And
(ExtractFileExt(Path + Rec.Name).ToLower <> '.lnk') And
(Directoryexists(Path + Rec.Name + '\') = False) then
begin
if (Pos(Path + Rec.Name, main.Memo1.Lines.Text) = 0) then
begin
main.ListBox1.Items.Add(Path + Rec.Name);
main.Memo1.Lines.Add(Path + Rec.Name)
end;
end;
GetAllSubFolders(Path + Rec.Name);
end;
until FindNext(Rec) <> 0;
finally
FindClose(Rec);
end;
except
on e: Exception do
ShowMessage(e.Message);
end;
end;
我的应用程序搜索选定文件夹和子文件夹中的所有文件,将它们压缩并将它们复制到您指定的另一个位置。
Application.ProcessMessages
命令用于确保应用程序看起来不会挂起并且用户不会将其关闭。因为例如查找 100 000 个文件可能需要一个小时左右...
我担心处理器的使用情况,内存并没有真正受到影响。
注意:备注是为了确保相同的文件不会被选择两次。
最佳答案
我发现以下性能问题:
- 调用
Application.ProcessMessages
有点贵。您正在轮询消息而不是使用阻塞等待,即GetMessage
。除了性能问题之外,使用Application.ProcessMessages
通常表明由于各种原因导致设计不佳,通常应该避免调用它。 - 非虚拟列表框在处理大量文件时表现不佳。
- 使用备忘录控件(GUI 控件)来存储字符串列表的成本非常昂贵。
- 每次添加到 GUI 控件时,它们都会更新和刷新,这是非常昂贵的。
Memo1.Lines.Text
的评价非常昂贵。- 使用
Pos
同样非常昂贵。 - 使用
DirectoryExists
既昂贵又虚假。搜索记录中返回的属性包含该信息。
我会进行以下更改:
- 将搜索代码移至线程中以避免需要
ProcessMessages
。您需要设计某种方法将信息传输回主线程以便在 GUI 中显示。 - 使用虚拟 ListView 来显示文件。
- 将您想要搜索重复项的文件列表存储在字典中,该字典为您提供
O(1)
抬头。请注意文件名不区分大小写,这是您迄今为止可能忽略的问题。这将取代备忘录。 - 使用
Rec.Attr
检查项目是否是目录。即检查Rec.Attr and faDirectory <> 0
.
关于delphi - 扫描文件夹/子文件夹/文件时如何减少CPU使用率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25301936/