如何显示长进程的GUI进度?

WeG*_*ars 1 delphi

我需要处理一些数据并且每5-10秒显示一次进度(我以百分比显示进度但我也更新了一些图表).我想在没有多线程的情况下这样做.循环可能很大.它可以从数百万开始,可以高达数十亿.

我可以使用GetTickCount:

const 
  RefreshEvery= 5000;

for x:= 1 to 10000000000 do
 if GetTickCount-OldTime> RefreshEvery then
 begin
   OldTime:= GetTickCount;
   if Assigned(FProgress) then FProgress(Self);
 end; 
Run Code Online (Sandbox Code Playgroud)

但是在循环中调用GetTickCount会执行数十亿次...

有关最有效的方法的任何想法?


为什么没有多线程?
这是一个很大的应用程序,在GUI进度模块中有一个小故障.我想解决这个问题,重新打包并交付它而不需要对其进行大的更改,这需要再次进行密集测试.多线程?......很酷,但后来......

J..*_*... 5

您的问题似乎是确定一种有效的方法来评估发布进度更新的时间间隔.如果你是针对线程方法设置的,那么你正在做的事情很好 - 没有太多改进它的方法.实际上,确定更新间隔的效率在线程代码中也是如此,因此无论线程是否相同,问题都是相同的.

您似乎没有问题的内容FProgress(self)(即:如何执行状态更新),这似乎也不是关于"冻结"GUI,所以我不会解决这些问题.

你的选择是

  • GetTickCount - 根据时间更新
  • if x mod 1000 = 0 - 基于循环变量更新
  • (类似的东西)if x shl 22 = 0 - 与上面相同,但是没有分裂的狡猾的mod 1024
  • 根据@LURD,你也可以使用if i and $3FF = 0类似性能的东西

如果你的循环根本没有任何肉,它们的性能几乎相同.去测试 :

program Project1;

uses Windows, SysUtils;

{$APPTYPE CONSOLE}    

var 
  i : integer;
  t0 : cardinal;
begin
  t0 := GetTickCount;
  for i := 0 to 1000000000 do begin
    if t0 - GetTickCount > 1000 then;
  end;
  t0 := GetTickCount - t0;
  WriteLn('GetTickCount : ' + IntToStr(t0));

  t0 := GetTickCount;
  for i := 0 to 1000000000 do begin
    if i mod 1000 = 0 then;
  end;
  t0 := GetTickCount - t0;
  WriteLn('i mod 1000 : ' + IntToStr(t0));

  t0 := GetTickCount;
  for i := 0 to 1000000000 do begin
    if i shl 22 = 0 then;
  end;
  t0 := GetTickCount - t0;
  WriteLn('i shl 22 : ' + IntToStr(t0));

  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

产生输出(对我来说)

 GetTickCount : 3978   
 i mod 1000 :   3386   
 i shl 22 :     2184
Run Code Online (Sandbox Code Playgroud)

最后一个选项大约是性能的两倍,但是如果你的循环做任何实质性的事情你可能不会注意到任何差异.


附录:

如果您需要满足自己,比特移位是一种准确的方法:

program Project1;

uses SysUtils;

{$APPTYPE CONSOLE}

var
  i : integer;
begin
  for i := 0 to 1000000000 do begin
    if (i shl 22 = 0) <> (i mod 1024 = 0) then
      WriteLn('not the same! : ' + IntToStr(i));
  end;
  WriteLn('complete.');
  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

请注意,它们i shl 22不相等i mod 1024,但对于相同的值,它们都为零i.

  • 我发现`i和$ 3FF = 0`比`i shl 22 = 0`快一点. (2认同)