2012-08-27 9 views
5

Tôi đang thực hiện một vòng lặp dài tải xuống hàng nghìn tệp. Tôi muốn hiển thị thời gian ước tính còn lại, vì có thể mất hàng giờ. Tuy nhiên, với những gì tôi đã viết, tôi nhận được số lượng trung bình là mili giây. Làm cách nào để chuyển đổi thời gian tải xuống trung bình này từ mili giây sang một số TDateTime?Làm cách nào để chuyển đổi mili giây sang TDateTime?

Xem nơi tôi đang thiết Label1.Caption:

procedure DoWork; 
const 
    AVG_BASE = 20; //recent files to record for average, could be tweaked 
var 
    Avg: TStringList; //for calculating average 
    X, Y: Integer; //loop iterators 
    TS, TE: DWORD; //tick counts 
    A: Integer; //for calculating average 
begin 
    Avg:= TStringList.Create; 
    try 
    for X:= 0 to FilesToDownload.Count - 1 do begin //iterate through downloads 
     if FStopDownload then Break; //for cancelling 
     if Avg.Count >= AVG_BASE then //if list count is 20 
     Avg.Delete(0); //remove the oldest average 
     TS:= GetTickCount; //get time started 
     try 
     DownloadTheFile(X); //actual file download process 
     finally 
     TE:= GetTickCount - TS; //get time elapsed 
     end; 
     Avg.Add(IntToStr(TE)); //add download time to average list 
     A:= 0; //reset average to 0 
     for Y:= 0 to Avg.Count - 1 do //iterate through average list 
     A:= A + StrToIntDef(Avg[Y], 0); //add to total download time 
     A:= A div Avg.Count; //divide count to get average download time 
     Label1.Caption:= IntToStr(A); //<-- How to convert to TDateTime? 
    end; 
    finally 
    Avg.Free; 
    end; 
end; 

PS - Tôi mở cửa cho cách khác nhau để tính tốc độ trung bình 20 (hoặc AVG_BASE) tải cuối cùng, vì tôi chắc chắn rằng chuỗi của tôi danh sách giải pháp không phải là tốt nhất. Tôi không muốn tính toán nó dựa trên tất cả các tải xuống, bởi vì tốc độ có thể thay đổi trong thời gian đó. Do đó, tôi chỉ kiểm tra lần cuối cùng 20.

Trả lời

10

Giá trị TDateTime về cơ bản là double, trong đó phần nguyên là số ngày và phần là thời gian.

Trong một ngày có được 24 * 60 * 60 = 86400 giây (SecsPerDay liên tục khai báo trong SysUtils) như vậy để có được A như TDateTime làm:

dt := A/(SecsPerDay*1000.0); // A is the number of milliseconds 

Cách tốt hơn để đồng hồ thời gian sẽ được sử dụng cấu trúc TStopWatch trong đơn vị Diagnostics.

Ví dụ:

sw.Create; 
.. 
sw.Start; 
// Do something 
sw.Stop; 
A := sw.ElapsedMilliSeconds; 
// or as RRUZ suggested ts := sw.Elapsed; to get the TimeSpan 

Để có được thời gian trung bình của bạn, hãy xem xét sử dụng kỷ lục moving average này:

Type 
    TMovingAverage = record 
    private 
    FData: array of integer; 
    FSum: integer; 
    FCurrentAverage: integer; 
    FAddIx: integer; 
    FAddedValues: integer; 
    public 
    constructor Create(length: integer); 
    procedure Add(newValue: integer); 
    function Average : Integer; 
    end; 

procedure TMovingAverage.Add(newValue: integer); 
var i : integer; 
begin 
    FSum := FSum + newValue - FData[FAddIx]; 
    FData[FAddIx] := newValue; 
    FAddIx := (FAddIx + 1) mod Length(FData); 
    if (FAddedValues < Length(FData)) then 
    Inc(FAddedValues); 
    FCurrentAverage := FSum div FAddedValues; 
end; 

function TMovingAverage.Average: Integer; 
begin 
    Result := FCurrentAverage; 
end; 

constructor TMovingAverage.Create(length: integer); 
var 
    i : integer; 
begin 
    SetLength(FData,length); 
    for i := 0 to length - 1 do 
    FData[i] := 0; 
    FSum := 0; 
    FCurrentAverage := 0; 
    FAddIx := 0; 
    FAddedValues := 0; 
end; 
+1

+1 cho TStopWatch. Lưu ý rằng trên một số máy tính, tôi thực sự thấy rằng các chức năng API Win32 cơ bản của TStopWatch không ổn định và không hoạt động đúng (Windows XP, trên một số chipset Intel Pentium 4 với chipset thời kỳ ICH4/ICH5). Không phải là một vấn đề nữa trên phần cứng hiện đại (Core2Duo và sau này), nhưng ... Tôi đã dành rất nhiều thời gian đo mili giây (cố gắng làm điều đó một cách chính xác) và Windows API đã cho tôi nhiều đau buồn vì cố gắng. (Tôi không nói rằng tôi muốn thời gian thực cứng, chỉ là một truy cập mili giây mà không đóng băng hoặc lảo đảo về phía trước) - TStopWatch là chính xác hơn nhiều so với GetTickCount! –

+0

+1 thực sự, bây giờ nếu chỉ tôi cũng có thể đưa các kích thước tập tin vào xem xét ....... câu chuyện khác nhau mặc dù ........ –

8

Thay vì TDateTime, bạn có thể sử dụng bản ghi TTimeSpan, bạn có thể tạo một phiên bản mới qua các dấu tích đã trôi qua đến constructor và từ đây bạn có thể sử dụng ngày, giờ, các thuộc tính phút, giây và Mili giây để hiển thị thời gian đã trôi qua. Bây giờ để tính toán thời gian còn lại, bạn cần tổng số byte để tải xuống và các byte tải xuống hiện tại.