好吧,让我来试试吧:
首先你的线程的新版本:
uses
IOUtils;
type
TFileFoundEvent = procedure(const Path: string; const SearchRec: TSearchRec) of object;
TSearchThread = class(TThread)
private
FPath: string;
FSearchRec: TSearchRec;
FFileFoundEvent: TFileFoundEvent;
protected
procedure Execute; override;
public
Constructor Create(const aPath: string; aFileFoundEvent: TFileFoundEvent); reintroduce;
end;
{ TSearchThread }
constructor TSearchThread.Create(const aPath: string; aFileFoundEvent: TFileFoundEvent);
begin
// Create the Thread non suspended
inherited Create(false);
// Copy parameters to local members.
FFileFoundEvent := aFileFoundEvent;
FPath := aPath;
// Make the sure the thread frees itself after execution
FreeOnTerminate := True;
end;
procedure TSearchThread.Execute;
var
FilterPredicate: TDirectory.TFilterPredicate;
begin
// FilterPredicate is an in-place anonymous method to be called each time the TDirectory.GetFiles finds a file
FilterPredicate := function(const Path: string; const SearchRec: TSearchRec): Boolean
begin
// Since we can not access from within Synchronize we need to copy iot to a member of the class
FSearchRec := SearchRec;
// You cannot access VCL objects directly from a thread.
// So you need to call Syncronize
// For more info look in the online help
// http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Classes.TThread.Synchronize
Synchronize(nil,
procedure
begin
FFileFoundEvent(FPath, FSearchRec);
end);
Result := True;
end;
// Do the search
TDirectory.GetFiles(FPath, TSearchOption.soTopDirectoryOnly, FilterPredicate)
end;
主要diffrence是我传递一个回调proceudre到的构造线。因为我使用TDirectory.GetFiles
来搜索文件。从放置一个列表框上的,然后调用它像这样:你会在IOUtils
然后,你需要使用它找到TDirectory.GetFiles
表单定义:
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
private
procedure FileFoundEvent(const Path: string; const SearchRec: TSearchRec);
public
{ Public declarations }
end;
...
implementation
procedure TForm1.FileFoundEvent(const Path: string; const SearchRec: TSearchRec);
begin
ListBox1.Items.Add(SearchRec.Name);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TSearchThread.Create(ExtractFilePath(Application.ExeName), FileFoundEvent);
end;
如果你不想看到正在进行的搜索结果,而是想要一些速度,你可以创建一个searchthread的版本,同时给你结果:
uses
IOUtils;
type
TSearchThread = class(TThread)
private
FSearchPath: String;
FResultBuffer: TStrings;
protected
procedure Execute; override;
public
constructor Create(const aSearchPath: string; aResultBuffer: TStrings); overload;
end;
constructor TSearchThread.Create(const aSearchPath: string; aResultBuffer: TStrings);
begin
inherited Create(false);
FSearchPath := IncludeTrailingPathDelimiter(aSearchPath);
FResultBuffer := aResultBuffer;
FreeOnTerminate := True;
end;
procedure TSearchThread.Execute;
var
FBuffer: TStringlist;
Filename: String;
begin
Synchronize(nil,
procedure
begin
FResultBuffer.Text := 'Searching ' + FSearchPath;
end);
FBuffer := TStringlist.Create;
for Filename in TDirectory.GetFiles(FSearchPath, TSearchOption.soAllDirectories, nil) do
FBuffer.Add(Filename);
Synchronize(nil,
procedure
begin
FResultBuffer.Assign(FBuffer);
end);
FreeAndNil(FBuffer);
end;
这个线程你必须有点不同的方式调用。
表单设置我仍然像以前一样:窗体上的列表框。
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
private
Stopwatch: TStopwatch;
procedure SearchThreadTerminate(Sender: TObject);
public
{ Public declarations }
end;
然后执行:
procedure TForm1.FormCreate(Sender: TObject);
begin
Stopwatch := TStopwatch.StartNew;
with TSearchThread.Create('C:\Program Files (x86)\Embarcadero\', ListBox1.Items) do
OnTerminate := SearchThreadTerminate;
end;
procedure TForm1.SearchThreadTerminate(Sender: TObject);
begin
Stopwatch.Stop;
Caption := 'Elapsed Milliseconds: ' + IntToStr(Stopwatch.ElapsedMilliseconds) + ' Files found: ' + IntToStr(ListBox1.Items.Count);
end;
这个版本的优点是速度快。更新屏幕很慢,第一个解决方案更新了它找到的每个文件的屏幕,而这个屏幕只更新屏幕两次。
试试吧。
这已经在这里覆盖了很多次。您无法从线程访问VCL对象。使用'TThread.Queue'或'TThread.Synchronize'。 –
您需要了解线程。您需要覆盖TThread的执行。 – MartynA
不是另一个*让我们通过直接*帖子从我的线程访问UI控件来违反所有规则。现在有几十个关于如何使用线程的Delphi问题。搜索他们,并找到一个示例,告诉你如何正确使用它们。你不得不在线程的Execute方法中重新声明所有的UI控件时,你的第一个线索应该是这样的。你应该马上知道你做错了什么。 –