Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Zeit berechnen/abschätzen bis eine Prozedur abgearbeitet ist


freedy - Do 10.02.05 19:39
Titel: Zeit berechnen/abschätzen bis eine Prozedur abgearbeitet ist
Hallo Forum!

Mir war mal wieder langweilig und da dachte ich mir, dass meinem Programm noch ein letzter Schliff fehlt. :)

Nein, ganz im Ernst... es wird so gefordert.

Aber hier nun mein Problem. Ich habe eine Prodezur laufen, die einige Berechnungen mit sich bringt. Da möchte ich gerne dem Benutzer zeigen, wie lange er noch warten muss. Kennt man ja aus vielen Progs.

Hier mal mein (reduzierter) Code:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
procedure TableCreateClick;
var
  Index : Integer;
  Line : String;
  EstimatedTime : TDateTime;
  t1, t2 : TDateTime;
  TimeStr : String;
begin
  try
    Screen.Cursor := crHourGlass;

    // Zeit holen
    t1 := Time;

    for Index := 0 to Count - 1 do
    begin

      // Hier wird die Berechnung ausgeführt

      // wenn das Zeitintervall zu klein ist, rechnet er immer mit NULL 
      // deshalb nur jeden 50. Schritt berechnen.
      if ((Count - Index) Mod 50 = 0then
      begin
        t2 := Time;
        EstimatedTime := (Count - Index) * (t2 - t1);
        TimeStr := FormatDateTime('nn:ss', EstimatedTime);

        if Label6.Caption <> TimeStr then
          Label6.Caption := TimeStr;
        t1 := Time;
      end;
    end;

  finally
    Screen.Cursor := crDefault;
  end;
end;


Anstelle von sinnvollen Ausgaben auf meinem Label, werden ständig wechselnde Zeiten ausgegeben.

Hat jemand sowas schon einmal gemacht? Danke für eure Tips.

Gruß
freedy


Delete - Do 10.02.05 19:44

Für gewöhnlich wird vor Anfang der Berechnung überschlagen oder manchmal sogar genau berechnet, wie lange der Vorgang dauert, dann die Skala-Einteilung(TProgressBar) vorgenommen und in regelmäßigen Abständen während der Berechnung der Fortschritt aktualisiert.


freedy - Do 10.02.05 20:05

Hm... okay. Klingt erstmal einleuchtend. Eine Progressbar habe ich auch schon. Das klappt.

Ich würde aber gerne zeigen, wie lange der Vorgang noch dauert in Minuten/Sekunden.

Denn in knapp 15sec. gibt es auf der ProgressBar gerade mal 1%. Den Benutzer interessiert, ob er sich einen Kaffee kochen kann, oder nicht. :wink:

Gruß
freedy


patrick - Do 10.02.05 22:41

damit hast du dir schon selbst die antwort gegeben:
alles was du machen musst ist folgendes:
wenn das programm für 1% 15 sekunden braucht, dann kannst du berechnen wie lange es für 100% brauchst.


patrick - Do 10.02.05 23:34

ich hab auf die schnelle dann mal eine entsprechende funktion erstellt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
{-----------------------------------------------------------------------------
  Procedure: CalcEstimateTime
  Version:   1.0.0.0
  Author:    Patrick || NetTraxX.de.vu
  Date:      10.02.2005 22:28:22
  Arguments: StartTime,CurrentTime,MaxProgress,CurrentProgress:integer
  Result:    single - Estimate time in seconds
  Purpose:   StartTime and CurrentTime have to be milliseconds
  Notes:
-----------------------------------------------------------------------------}

function CalcEstimateTime(StartTime,CurrentTime,MaxProgress,CurrentProgress:integer):single;
var DivTime,
    ProgressDiv:integer;
begin
  DivTime := CurrentTime - StartTime;
  ProgressDiv := (MaxProgress - CurrentProgress);
  result := (DivTime / CurrentProgress) * ProgressDiv / 1000;
end;


aufrufbeispiel:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var
  Form1: TForm1;
  GetStartTime: integer;
implementation

...

procedure TForm1.Button1Click(Sender: TObject);
begin
  GetStartTime:=GetTickCount;
  Timer1.Enabled:=true;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
var GetCurrentTime:integer;
begin
  ProgressBar1.StepIt;
  GetCurrentTime:=GetTickCount;
  Edit1.Text:=FloatToStr(CalcEstimateTime(GetStartTime,GetCurrentTime,progressbar1.Max,progressbar1.Position));
end;


Spaceguide - Fr 11.02.05 15:14

Das ganze bitte nicht bei CurrentProgress=0 aufrufen ;-)


patrick - Fr 11.02.05 18:03

jo, kann man nachvollziehen ^^
ich hab meine "schlampige" version überarbeitet und ne sicherheitsabfrage eingebaut.
hier die version 1.0.1.0:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
{-----------------------------------------------------------------------------
  Procedure: CalcEstimateTime
  Version:   1.0.1.0
  Author:    Patrick || NetTraxX.de.vu
  Date:      10.02.2005 22:28:22
  Arguments: StartTime,CurrentTime,MaxProgress,CurrentProgress:integer
  Result:    single - Estimate time in seconds
                    - "-1" on error
  Purpose:   StartTime and CurrentTime have to be milliseconds
  Notes:
-----------------------------------------------------------------------------}

function CalcEstimateTime(StartTime,CurrentTime,MaxProgress,CurrentProgress:integer):single;
var DivTime,
    ProgressDiv:integer;
begin
  DivTime := CurrentTime - StartTime;
  ProgressDiv := (MaxProgress - CurrentProgress);

  if (DivTime >= 0and (ProgressDiv >= 0and (CurrentProgress > 0then
  begin
    result := (DivTime / CurrentProgress) * ProgressDiv / 1000;
  end
  else
  begin
    result:=-1;
  end;
end;

im fehlerfall wir als resultat -1 ausgegeben.
das kommt davon wenn man spät nachts ne 0815 programmierung hinrotzt :oops: