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

时间:2015-03-06 15:45:26

标签: delphi

我有一个列表框,其中列出了文件夹中的所有文件。对于列表框的每个元素,我想运行一个函数。如果函数结果为false,那么我想将列表框项移动到名为ListBox_fisiere_restore_vme的单独列表框中。如果函数结果为true,那么我想将列表框项添加到名为ListBox_continut_ftp的列表框中。这应该很容易。问题是,无论函数结果如何,项目都会被移动到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;

我不知道我做错了什么。

2 个答案:

答案 0 :(得分:1)

我怀疑你看到的问题与你在测试中串联延迟的循环运行有关。如果您正在测试100个文件,则需要100秒,每秒测试一个文件。一千个文件需要1000秒。如果任何给定的文件在检查时在那个一秒钟的窗口中没有变化,它将给出您正在观察的结果。

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;

第一种方法就像试图击中一个移动的目标。第二种方法一次性捕获文件状态,并在相同的相对时间间隔内测量所有变化。运行只需几秒钟。

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

答案 1 :(得分:0)

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代码。但我确定你会明白这一点。