在 Delphi 中列出一个巨大目录中的所有 exe 文件的最快方法是什么?

What's the fastest way to list all the exe files in a huge directory in Delphi?

目前我正在做这样的事情:

var
    Files: TArray<String>;

if IncludeSubDirs then
    Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soAllDirectories)
else
    Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soTopDirectoryOnly);

Path 是用户定义的 String 可以指向任何现有目录。对于包含大量文件和 IncludeSubDirs = True(例如 C:\Windows\)的“大”目录,GetFiles 需要很长时间(如 30+ 秒)。

用 Delphi(如果有的话)在 Windows 下的“大”目录中列出所有 exe 文件的最快方法是什么?

我做了一些基准测试,对于一个巨大的目录,FindFirst / FindNext 比使用 TDirectory 快大约 1.5% 到 3%。我会说两者的速度相当(对于我的用例,我每分钟节省了大约 1 秒)。我最终使用 FindFirst / FindNext 因为你会逐渐获得结果而不是一次全部,内存管理似乎更好并且更容易中途取消。我还使用了 TThread 来避免阻塞我的 UI.

这就是我最终得到的结果:

procedure TDirectoryWorkerThread.AddToTarget(const Item: String);
begin
    if (not Self.Parameters.DistinctResults) or (Self.Target.IndexOf(Item) = -1) then
        Self.Target.Add(Item);
end;

procedure TDirectoryWorkerThread.ListFilesDir(Directory: String);

var
    SearchResult: TSearchRec;

begin
    Directory := IncludeTrailingPathDelimiter(Directory);

    if FindFirst(Directory + '*', faAnyFile, SearchResult) = 0 then
    begin
        try
            repeat
                if (SearchResult.Attr and faDirectory) = 0 then
                begin
                    if (Self.Parameters.AllowedExtensions = nil) or (Self.Parameters.AllowedExtensions.IndexOf(ExtractFileExt(SearchResult.Name)) <> -1) then
                        AddToTarget(Directory + SearchResult.Name);
                end
                else if Self.Parameters.IncludeSubDirs and (SearchResult.Name <> '.') and (SearchResult.Name <> '..') then
                    ListFilesDir(Directory + SearchResult.Name);
            until Self.Terminated or (FindNext(SearchResult) <> 0);
        finally
            FindClose(SearchResult);
        end;
    end;
end;