【问题标题】:Delphi scanning for database directories using multi threadingDelphi 使用多线程扫描数据库目录
【发布时间】:2014-09-14 20:00:44
【问题描述】:

我需要扫描驱动器以查找包含我的数据库文件的目录,以将它们添加到 BDE 路径。 如何让我的代码使用线程更快地完成它? 我使用的是delphi 2007,所以不支持omniThread。 我需要知道如何制作线程,以及如何执行它。 这是我的代码: 谢谢。

procedure TMainFrm.RestoreDBDirs;
var
  Lst: TStringList;
  Dirs: string;
  Counter, j, LstFrom, LstTo: integer;
  SearchRec: TSearchRec;
  ST: TScanThread;    
begin
  Screen.Cursor:= crHourGlass;
  try
    try
      ChangeAlias(AliasCombo);//After this procedure the tables are closed
    except
    end;
    Lst:= TStringList.Create;
    Lst.Clear;
    Counter:= 0;

if Assigned(ChooseDrvFrm) then
with ChooseDrvFrm do
begin
  Lst.Add(lvDrives.Selected.Caption);
  Dirs:= lvDrives.Selected.Caption;

  Progress1.Position:= 0;
  Progress1.Visible:= True;
  stBar1.SimpleText:= 'Searching for Databases...';
end
else
begin
  Lst.Add(GetSystemDrive);
  Dirs:= GetSystemDrive;
end;

repeat
  // Update Progress Bar
  if Assigned(ChooseDrvFrm) then
  with ChooseDrvFrm do
  begin
    Progress1.StepBy(1);
    if Progress1.Position = Progress1.Max then
      Progress1.Position:= 0;
  end;

  Dirs:= Lst.Strings[Counter] +'\';
  if (Dirs <> '.') and (Dirs <> '..')then
    if FindFirst(Dirs +'*.*', faDirectory, SearchRec) = 0 then
    begin
      if ((SearchRec.Attr and faDirectory) > 0)
      and (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
      begin
        Lst.Add(Dirs + SearchRec.Name);

        if Assigned(ChooseDrvFrm) then
          ChooseDrvFrm.stBar1.SimpleText:= Dirs + SearchRec.Name;
      end;

      while FindNext(SearchRec) = 0 do
        if ((SearchRec.Attr and faDirectory) > 0) and
            (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
        begin
          Lst.Add(Dirs + SearchRec.Name);
          if Assigned(ChooseDrvFrm) then
            ChooseDrvFrm.stBar1.SimpleText:= Dirs + SearchRec.Name;
        end;
    end;
  Counter:= Counter + 1;
  FindClose(SearchRec);
until Counter = Lst.Count;

Dirs:= '';

if Assigned(ChooseDrvFrm) then
  ChooseDrvFrm.Progress1.Position:= 0;

for Counter:= 0 to Lst.Count - 1 do
begin
  if Assigned(ChooseDrvFrm) then
  with ChooseDrvFrm do
  begin
    Progress1.StepBy(1);
    if Progress1.Position = Progress1.Max then
      Progress1.Position:= 0;
  end;

  if (FileExists(Lst.Strings[Counter] + '\Crt.DB'))
  and (FileExists(Lst.Strings[Counter] + '\Ds.DB'))
  and (FileExists(Lst.Strings[Counter] + '\Turim.DB'))
  and (FileExists(Lst.Strings[Counter] + '\Rprt.DB'))
  and (UpperCase(Lst.Strings[Counter]) <> UpperCase('C:\My Installations\Data'))
  and (UpperCase(Lst.Strings[Counter]) <> UpperCase(ExtractFileDir(ParamStr(0)))) then
  try
    if Assigned(ChooseDrvFrm) then
      ChooseDrvFrm.stBar1.SimpleText:= 'Restoring Databases: '+ Lst.Strings[Counter];

    RestoreAlias(Lst.Strings[Counter]);
  except
    on EDatabaseError do;
  end;
end;

if Assigned(ChooseDrvFrm) then
with ChooseDrvFrm do
begin
  Progress1.Position:= 0;
  Progress1.Visible:= False;
  stBar1.SimpleText:= 'Done';
  MessageDlg('Databases succesfully restored', mtInformation, [mbYes], 0);
  Close;
end;

>     FillAliasCombo;   finally
>     Lst.Free;
>     Screen.Cursor:= crDefault;   end;

【问题讨论】:

  • 这很可能是一个糟糕的主意。不是因为线程,而是因为涉及对非索引网络资源的大量解析。即使您使用线程,您也必须等到所有线程完成,并且访问网络驱动器的超时可能会超过几分钟。
  • front page 表示支持 D2007。

标签: multithreading delphi delphi-2007 findfirst database-scan


【解决方案1】:

对于传统的旋转磁盘,线程无法帮助您。您的任务受磁盘限制而不是 CPU 限制,并且线程会导致磁盘磁头移动效率低下。尝试使用多个线程执行此操作可能会比单个线程慢。

对于固态驱动器或网络驱动器,您的进程仍然是磁盘绑定的。但是,使用线程并行执行任务可以减轻磁盘访问过程的一些延迟并提高性能。

需要进行一些实验才能确定如何最好地扫描磁盘,并且可能需要针对不同磁盘类型采取不同的策略。

我认为首先要尝试的是生产者/消费者方法。枚举目录的生产者线程。然后多个消费者读取这些目录的内容。您可能希望将多个目录批处理到单个任务中,以最大程度地减少线程开销的影响。

【讨论】:

  • 谢谢。我想也许这是可能的,因为文件系统被索引或我不知道的东西......也许还有另一种方式?
  • 您可以尝试检查:stackoverflow.com/questions/3153428/… 但请记住,索引是平台相关的(在 W7 之前您可能必须使用另一个 API)并且可以关闭。
  • 可以选择使用索引服务。只要目标被编入索引。
  • 大卫,您的说法仅在谈到较慢的机械磁盘时才是正确的,另一方面,SSD 将受益于更高的 IO 队列深度......
  • 多线程在这种情况下没有帮助不一定是真的。如果以前访问过目录内容,它们很可能在缓存中,因此搜索根本不会触及磁盘。这里提出的问题是:为什么它一开始就太慢了?我阅读该代码的方式是在整个驱动器中搜索包含某些特定文件名的目录。这真的有必要吗?不能减少需要搜索的路径吗?不管怎样:这个特定的例程多久被使用一次?尝试和优化它真的有意义吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多