在Delphi中计算上传速度问题

时间:2014-03-18 16:30:07

标签: delphi file-upload

我使用delphi 2010和聪明的互联网套件组件我上传文件并想要计算上传速度..

我尝试了这段代码,但它在标签上给了我“INF”+错误的速度!

该代码有什么不对?

private
  FBytesProceed : Int64;
  FTimeStamp : TDateTime;
  FSpeed : double;
end;

procedure TForm2.clHttp1SendProgress(Sender: TObject; ABytesProceed,
  ATotalBytes: Int64);
var
  LTimeStamp : TDateTime;
begin
  LTimeStamp := Now;
  if FBytesProceed < ABytesProceed then
  begin
    // calculating bytes per second
    FSpeed := ( ABytesProceed - FBytesProceed ) {bytes}
            / ( ( LTimeStamp - FTimeStamp ) {days}
              * 24 {hours}
              * 60 {minutes}
              * 60 {seconds} );
  end;
  FBytesProceed := ABytesProceed;
  FTimeStamp := LTimeStamp;

label1.Caption  := Format(' speed %n Kbps',[FSpeed / 1024]);

end;

2 个答案:

答案 0 :(得分:2)

正如您所遇到的,系统计时器的分辨率非常好。我似乎记得它可以低至50毫秒。以下是解决此问题的两种方法,其中一些方法取决于程序的结构。

一,你可以使用常规的TTimer设置为2秒或任何你想要的间隔。每次触发时都会获得字节数,将其与上次触发定时事件的时间进行比较,并使用上传速率设置标题。这显然只有在你处理非阻塞上传时才有效。如果你不想使用TTimer,你也可以在一个单独的线程中执行此操作,并且每隔几秒检查一次上传。

另一种方法是继续做你正在做的事情,但只在一秒钟之后更新上传率。我建议使用GetTickCount()而不是Now()(因为你实际上不需要日期,只需一个计数器)。 GetTickCount()返回一个表示毫秒的整数,而不是浮点值。将字节数开始为0.对于每个上传的块,将该数量添加到字节数。然后检查滴答计数。如果自上一个字幕更新后已经过了一秒钟,请更新标题并将字节数设置回零,并记录下次上传块时的滴答计数。

(只是一些伪代码来说明我在第二个选项中所说的内容)

t := GetTickCount();
n := t - LastTick;
if (n > 2000) then  //2 seconds
begin
    rate := ByteCount / n;

    caption := format(....);

    LastTick := t;
    ByteCount := 0;     
end;

答案 1 :(得分:0)

“现在”不是一个好用的计时器。像GetTickCount这样的东西更准确。 GetTickCount非常有用,因为它自系统启动以来以非常快的速度提供ms。看看更长的时间也更好。我做了类似这样的事情,如果你不使用某种窗口,你的速度最终会在整个节目中摇摆不定。我发现最好保留最后x个值,然后使用它们来计算性能。它为用户提供了更顺畅的反馈。

例如,这样的事情应该有效(使用10个值):

type
  TDataBlock = record
    DataTransferred: Int64;
    TimerTick: Cardinal;
  end;

  TForm2 = class(TForm)
    ...
  private
    FBlocks: TList<TDataBlock>;
    FLastAmount: Integer;
    FPreviousProceed: Int64;
    FPreviousTickCount: Cardinal;
    ...
  end;

  procedure TForm2.clHttp1SendProgress(Sender: TObject; ABytesProceed,
      ATotalBytes: Int64);
  var
    CheckTickCount: Cardinal;
    DataBlock: TDataBlock;
    Speed: Int64;
    TotalTicks: Cardinal;
    TotalData: Int64;
  begin
    CheckTickCount := GetTickCount;
    DataBlock.DataTransferred := ABytesProceed - FPreviousProceed;
    DataBlock.TimerTick := CheckTickCount - FPreviousTickCount;
    FBlocks.Add(DataBlock);
    if FBlocks.Count > 10 then
      FBlocks.Delete(0); // Make sure we keep our window at the last 10 values

    TotalTicks := 0;
    TotalData := 0;
    for DataBlock in FBlocks do
    begin
      TotalTicks := TotalTicks + DataBlock.TimerTick;
      TotalData := TotalData + DataBlock.DataTransferred;
    end;

    // calculating bytes per second
    Speed := TotalData {bytes} * 1000 div TotalTicks {ms};

    label1.Caption  := Format(' speed %n Kbps',[Speed / 1024]);
    FPreviousProceed := ABytesProceed;
    FPreviousTickCount := CheckTickCount;
  end;

您显然需要创建列表并在开始之前初始化所有变量。