设置一个起始时间dtStart,每循环一次记录时间dtNow,同时取得执行一次需要的时间fTime,用fTime*循环次数,就可以得到总时间。

var dtStart,dtNow: TDateTime;
    fTime,AllTime,fRest: Float;
    iMin,iSec: Integer;
    ii: Integer;
    FirstLoop: Boolean;
begin
  dtStart := Now;
  FirstLoop := True;
  for ii := 0 to 10000 do
  begin
    Application.ProcessMessage;
    
    //本次循环结束
    dtNow := Now;
    if FirstLoop then
    begin
      fTime := Now - dtStart;
      AllTime := fTime * 10000;  //总时间
      FirstLoop := False;
    end;
    fTime := dtNow - dtStart;
    fRest := AllTime - fTime;
    //自己取转换为分钟和秒吧
  end;
end;

解决方案 »

  1.   

    楼上的程序不行,朋友难道你看不出来吗?    if FirstLoop then
    段代码只会执行一次,又怎么能实时知道逝去时间,”自己取转换为分钟和秒吧”,怎么取?我不会,希望朋友们能给出具体的代码,不要只说想法好吗?
      

  2.   

    这里:Var Starting,Ending,Interval,Total,Remain, Passing,I,Count: Cardinal;
       Totals,Remains: String;
    begin
    Totals := '大约需1小时';
    Remains := '还剩1小时';
    Total := 3600000;
    Remain := 3600000;
    Passing := 0;
    Starting := GetTickCount;
    For I:=1 to Count do
    begin
      {Here do your processing}
      Ending := GetTickCount;
      Interval := Ending - Starting;
      Inc(Passing,Interval);  Total := Count * Interval;
      Application.ProcessMessages;
      Remain := Total - Passing;
      Totals := Format('大约需%d分%d秒',[Total div 60000,(Total mod 60000) div 1000]);
      Remains := Format('还剩%d分%d秒',[Remain div 60000,(Remain mod 60000) div 1000]);
    end;
    end;
      

  3.   

    Interval := Ending - Starting;
     Inc(Passing,Interval);
    肯定不对,这样是把所有循环中的时刻与开始的时刻差累加,而实际上,只有当前的GetTickCount才是逝去时间。所以Totals和Remains不对。
      

  4.   

    不好意思,少了一句话:procedure DoingIt(Count: Carinal);
    var Starting,Ending,Interval,Total,Remain, Passing,I: Cardinal;
       Totals,Remains: String;
    begin
      //Count := 10000;
      Totals := '大约需1小时';
      Remains := '还剩1小时';
      Total := 3600000;
      Remain := 3600000;
      Passing := 0;
      Starting := GetTickCount;
      For I:=1 to Count do
      begin
        {Here do your processing}    Ending := GetTickCount;
        Interval := Ending - Starting;
        Inc(Passing,Interval);    Total := Count * Interval;
        Remain := Total - Passing;
        Totals := Format('大约需%d分%d秒',[Total div 60000,(Total mod 60000) div 1000]);
        Remains := Format('还剩%d分%d秒',[Remain div 60000,(Remain mod 60000) div 1000]);    Application.ProcessMessages;    Starting := Ending;
      end;
    end;
      

  5.   

    Starting := Ending;应该放在Ending := GetTickCount;前面,你考虑不周全,我们应该都在要么循环头取时间,要么都在循环尾取时间,如果把Ending与Starting分别放在循环头跟循环尾取的话,就存在毫秒级的误差,毕竟在内存中的操作指令也是需要时间的。
      

  6.   

    Totals := '大约需1小时';
      Remains := '还剩1小时';
    是预估的,但我不喜欢这样限死了,程序一开始运行时的显示问题很让我头痛。
      

  7.   

    //Totals := '大约需1小时';
    //Remains := '还剩1小时';
    去掉就是了啊!只要进入循环,执行一条你的操作,就可以显示比较正确的提示了。
    在这之前,你可以干点别的,吸引用户的注意力!变魔术吧!
      

  8.   

    哎,这样啊,我给出算法思想,仅供参考,自己实现:
    因为是估计的时间,Windows也是,我们可以这样,要完全精确是不可能得:
    EsTime:=0;for i:=0 to 1000 do
    begin
      ALoopTimeStart:=Gettickcount
      ////Loop
      ... 
      ALoopTimeEnd:=GettickCount;
      EsTime:=EsTime+ALoopTimeStart-ALoopTimeEnd;
      AvgTime:= (AvgTime*(i-1) + (ALoopTimeStart-ALoopTimeEnd)) / i
      msg1:=Format('Total Time:%d',[AvgTime*1000]);
      msg2:=format('Es time:%d',[EsTime]);
    end;
    至于时间的转化,可以参考楼上的。
      

  9.   

    ………………………………………@v@
    …………………………………………
    有一大车啊!
    ……
    procedure DoingIt(Count: Carinal); 
    var 
       Starting,Ending,Interval,Total,Remain, Passing,I:Cardinal;       Totals,Remains: String;
     begin //Count := 10000; 
        Totals := '大约需1小时';
        Remains := '还剩1小时'; 
        Total := 3600000; 
        Remain := 3600000; 
        Passing := 0; 
        Starting := GetTickCount;
         For I:=1 to Count do begin {Here do your processing}
          Ending := GetTickCount; Interval := Ending - Starting; Inc(Passing,Interval); Total := Count * Interval; Remain := Total - Passing; Totals := Format('大约需%d分%d秒',[Total div 60000,(Total mod 60000) div 1000]); Remains := Format('还剩%d分%d秒',[Remain div 60000,(Remain mod 60000) div 1000]); Application.ProcessMessages; Starting := Ending; end; end; //不过,肯定不会这是样的:)不会有人用这样的
    方法有,但如果用自己的算法就是有点效果不是很好,你不如直接用WINAPI;
      

  10.   

    >问题
    事情应该基于估计和统计:最开始时(循环开始前)没有人能知道需要多少时间能完成,所以在完成第一个循环前,只能是不显示或显示一个估计数“大约一小时或小于一小时”;
    在完成第一个循环后,或者在N个循环后总算是过了1ms,那么就可以依据以前的数据来统计时间总数及剩余时间,即 所用时间数÷已经循环数 为目前所知的平均数,当然这个数应该在分子和分母都不为零的情况下才能开始计算,设这个数为k。那么,时间总数 = 总循环数×k = 总循环数×所用时间数÷已经循环数
    剩余时间数 = (总循环数-已经循环数)×k = (总循环数-已经循环数)×所用时间数÷已经循环数当然,每过一个循环都要重新计算一下k,就象Windows的复制或IE的下载进度时间一样,其速度不是均速的,甚至出现估计时间增多的情况。剩下的一个问题就是时间显示的技巧了,这个应该比较好办,拆成分和秒,如果分为0则不显示。其实了解算法就已经编码了,但你非要,那就给出伪代码吧:var
      i: Integer;
      dwBegin: LongWord; // 开始的系统时间
      dwNow: LongWord; // 每次取系统时间
    begin
      设置总时间和剩余时间为空或“1小时”;  dwBegin := GetTickCount; // 以毫秒为单位
      for i:=1 to 循环总数 do
      begin
        你的代码;
        
        dwNow := GetTickCount;
        if dwNow>dwBegin then
        begin
          显示总时间( 循环总数*(dwNow-dwBegin) div i div 1000 );
          显示剩余时间( (循环总数-i)*(dwNow-dwBegin) div i div 1000 );
        end;
      end;
    end;>Kingron(对CSDN愤怒中……) 
    老兄出了什么事?为何愤怒?
      

  11.   

    你可以得到已经执行多长时间,但你不能得到"还需要多长时间",Windows的Copy是可以通过Copy速度大致推断"还需要多长时间",你这里没有可以推断的依据,除非计算没一次循环平均使用的时间.