Delphi - 对于每个列表框项目 运行 一个函数并根据函数结果移动项目

Delphi - For each listbox item run a function and move item according to the function result

我有一个列表框,其中列出了文件夹中的所有文件。对于列表框的每个元素,我想 运行 一个函数。如果函数结果为假,那么我想将列表框项目移动到一个名为 ListBox_fisiere_restore_vme 的单独列表框中。如果函数结果为真,那么我想将列表框项添加到名为 ListBox_continut_ftp 的列表框中。这应该很容易 do.The 问题是,无论函数结果如何,项目总是被移动到 ListBox_fisiere_restore_vme。

我对每个列表框项目使用的函数:

function GetFileSize_mmg(const FileName: string): Int64;
var
  fad: TWin32FileAttributeData;
begin
 if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then RaiseLastOSError;
  Int64Rec(Result).Lo := fad.nFileSizeLow;
  Int64Rec(Result).Hi := fad.nFileSizeHigh;
end;    

function does_size_changes(nume_fisier: string; interval: integer;Memo_loguri: TMemo): boolean;
var
  size1, size2: Int64;
begin
  size1:=0;
  size2:=0;  
  size1 := GetFileSize_mmg(nume_fisier);
  delay(interval);
  size2 := GetFileSize_mmg(nume_fisier);

  if size1 <> size2 then
  begin
    Result := true;
    Memo_loguri.Lines.Add(datetimetostr(now) + ' - filename "'+nume_fisier+'" grows');
  end
  else
  begin
    Result := false;
    Memo_loguri.Lines.Add(datetimetostr(now) + ' - filename "'+nume_fisier+'" is not in use');
  end;
end;

导致此问题的循环具有以下代码:

procedure Tform2.OnSchedule_1_Trigger(Sender: TScheduledEvent);
var
nume_fisier:string;
i:integer;
begin
listbox_fisiere_in_uz.Clear;
listbox_fisiere_restore_vme.Clear;
DSiEnumFilesToSL(edit_watch_folder.text+edit_masca_fisiere.text, 0, listbox_fisiere_in_uz.Items, true, false );  
for i := ListBox_fisiere_in_uz.Items.count - 1 downto 0 do 
begin
   if does_size_changes(ListBox_fisiere_in_uz.Items[i], 1000, Memo_loguri) then        
    begin            
     listbox_continut_ftp.Items.Add(ListBox_fisiere_in_uz.Items[i]);
    end
     else
    begin
     ListBox_fisiere_restore_vme.Items.Add(ListBox_fisiere_in_uz.Items[i]);  
     end;
    end;

我看不出哪里做错了。

delay(interval)有多长?尝试增加它。

但这是错误的观念。如果 delay(interval) 是 100 毫秒,这意味着您有超过一分半(100 秒)的时间来循环 1000 个文件。如果我是你,我会使用计时器和一些字符串网格而不是列表框。

每个 2 列字符串网格可以在第 0 列包含文件名,在第 1 列包含文件大小。四个网格 - stringGrid_continut_ftp, stringGrid__fisiere_restore_vme, stringGrid_oldstringGrid_current

Timer1.timer 必须在 stringGrid_current 中获取默认文件名和大小,将它们与 stringGrid_old 进行比较,并且根据结果必须在前两个字符串网格之一中插入一行.最后 stringGrid_old 必须具有来自 stringGrid_current 的所有值,并且下一个计时器事件已准备好开始。

很抱歉只给出了解释,但现在我对 c++、wix 和批处理文件感到厌烦,无法专注于编写高质量的 delphi 代码。但我相信你会明白的。

我怀疑您看到的问题与以下事实有关:您 运行 正在通过与测试串联的延迟循环。如果您要测试 100 个文件,则需要 100 秒,每秒测试一个文件。一千个文件将花费 1000 秒。如果任何给定文件在检查时的那一秒内没有变化 window,它将给出您正在观察的结果。

for i := 0 to n-1 do
begin
  s1 := sizeoffile( fn[i] );
  delay( 1000 ); // pause one second
  s2 := sizeoffile( fn[i] );

  if (s1 <> s2) then
    addToLog( 'file size of '+fn[i]+' DID change' )
  else
    addToLog( 'file size of '+fn[i]+' did NOT change' )
end;

将这种行为与这种方法进行比较,无论 'n':

只需要几秒钟就可以达到 运行
var
  initialFileSize, newFileSize : array of Int64;

. . .

// get initial file sizes
for i := 0 to n-1 do
  initialFileSize[i] := sizeoffile( fn[i] );

delay( 1000 ); // pause one second

// get new file sizes
for i := 0 to n-1 do
  newFileSize[i] := sizeoffile( fn[i] );

for i := 0 to n-1 do
begin
  if (initialFileSize[i] <> newFileSize[i]) then
    addToLog( 'file size of '+fn[i]+' DID change' )
  else
    addToLog( 'file size of '+fn[i]+' did NOT change' )
end;

第一种方法就像试图击中一个移动的目标。第二种方法一次捕获所有文件状态,并在相同的相对时间间隔内测量所有更改。 运行.

只需几秒钟

我怀疑后一种方法更接近您的意图。