Delphi поиск файлов в потоке
Получил эту довольно простую функцию для поиска файлов:
function FindFiles(const Path, Mask: string; IncludeSubDir: boolean): integer;
var
FindResult: integer;
SearchRec: TSearchRec;
begin
Result := 0;
FindResult := FindFirst(Path + Mask, faAnyFile - faDirectory, SearchRec);
while FindResult = 0 do
begin
//!!!!!!!! This must synchronize Form1.Memo2.Lines.Add(Path + SearchRec.Name);
Result := Result + 1;
FindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
if not IncludeSubDir then
Exit;
FindResult := FindFirst(Path + '*.*', faDirectory, SearchRec);
while FindResult = 0 do
begin
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
Result := Result + FindFiles(Path + SearchRec.Name + '\', Mask, True);
FindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
Это называется с:
FindFiles('C:\','*.*',TRUE)
Как разбить это на поток Delphi? Этот код соответствует моим потребностям (d2010) Мне просто нужно поместить его (или его части) в поток. Спасибо
3 ответа
Может как то так?
unit Unit2;
interface
uses
SysUtils, Classes;
type
TFileSearcher = class(TThread)
private
{ Private declarations }
FPath, FMask: string;
FIncludeSubDir: boolean;
FItems: TStrings;
function FindFiles: integer;
procedure UpdateTheMemo;
public
constructor Create(CreateSuspended: boolean; const Path, Mask: string; IncludeSubDir: boolean);
protected
procedure Execute; override;
end;
implementation
uses Unit1;
{ TFileSearcher }
constructor TFileSearcher.Create(CreateSuspended: boolean; const Path, Mask: string;
IncludeSubDir: boolean);
begin
inherited Create(CreateSuspended);
FPath := Path;
FMask := Mask;
FIncludeSubDir := IncludeSubDir;
end;
procedure TFileSearcher.Execute;
begin
FItems := TStringList.Create;
try
FindFiles;
Synchronize(UpdateTheMemo);
finally
FItems.Free;
end;
end;
procedure TFileSearcher.UpdateTheMemo;
begin
Form1.Memo2.Lines.Assign(FItems);
end;
function TFileSearcher.FindFiles: integer;
var
FindResult: integer;
SearchRec: TSearchRec;
ThisPath: string;
begin
ThisPath := FPath;
Result := 0;
FindResult := FindFirst(FPath + FMask, faAnyFile - faDirectory, SearchRec);
while FindResult = 0 do
begin
FItems.Add(FPath + SearchRec.Name);
Result := Result + 1;
FindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
if not FIncludeSubDir then
Exit;
FindResult := FindFirst(IncludeTrailingBackslash(ThisPath) + '*.*', faDirectory, SearchRec);
while FindResult = 0 do
begin
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
FPath := IncludeTrailingBackslash(ThisPath + SearchRec.Name);
FIncludeSubDir := true;
Result := Result + FindFiles();
end;
FindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
end.
Если вы хотите, чтобы элементы добавлялись в элемент управления VCL один за другим, вы теряете некоторые преимущества многопоточности, но, конечно, это можно сделать:
unit Unit2;
interface
uses
SysUtils, Classes;
type
TFileSearcher = class(TThread)
private
{ Private declarations }
FPath, FMask: string;
FIncludeSubDir: boolean;
FItemToAdd: string;
function FindFiles: integer;
procedure UpdateTheMemo;
public
constructor Create(CreateSuspended: boolean; const Path, Mask: string; IncludeSubDir: boolean);
protected
procedure Execute; override;
end;
implementation
uses Unit1;
{ TFileSearcher }
constructor TFileSearcher.Create(CreateSuspended: boolean; const Path, Mask: string;
IncludeSubDir: boolean);
begin
inherited Create(CreateSuspended);
FPath := Path;
FMask := Mask;
FIncludeSubDir := IncludeSubDir;
end;
procedure TFileSearcher.Execute;
begin
FindFiles;
end;
procedure TFileSearcher.UpdateTheMemo;
begin
Form1.Memo2.Lines.Add(FItemToAdd);
end;
function TFileSearcher.FindFiles: integer;
var
FindResult: integer;
SearchRec: TSearchRec;
ThisPath: string;
begin
ThisPath := FPath;
Result := 0;
FindResult := FindFirst(FPath + FMask, faAnyFile and not faDirectory, SearchRec);
while FindResult = 0 do
begin
FItemToAdd := FPath + SearchRec.Name;
Synchronize(UpdateTheMemo);
Result := Result + 1;
FindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
if not FIncludeSubDir then
Exit;
FindResult := FindFirst(IncludeTrailingBackslash(ThisPath) + '*.*', faDirectory, SearchRec);
while FindResult = 0 do
begin
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
FPath := IncludeTrailingBackslash(ThisPath + SearchRec.Name);
FIncludeSubDir := true;
Result := Result + FindFiles();
end;
FindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
end.
Решение на основе OmniThreadLibrary, которое использует сообщения вместо Synchronize, можно найти здесь.
Посмотрите на мой ответ Indy 10 IdTCPClient Чтение данных с использованием отдельного потока? и содержащаяся в нем ссылка для более элегантного способа запуска данной функции внутри потока с использованием анонимных методов. Идея состоит в том, чтобы однажды реализовать класс, который выполняет любой TProc
внутри потока. Функция анонимного метода позволяет вам легко определить это TProc
на месте и с доступом ко всем локальным переменным вызывающего контекста.