我使用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;
答案 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;
您显然需要创建列表并在开始之前初始化所有变量。