![]() |
Progressbar einbinden
Hallo Zusammen!
Folgendes Problem: Ich hab eine Programm, das in eine Textdatei schreibt und zwar mit einer "for"-Schleife. Frage: Wie kann ich, ohne das Programm (also die Schreibgeschwindigkeit) zu sehr auszubremsen, eine Progressbar einbinden, die den Vorgang visuell veranschaulicht. folgendes ist mir schon klar^^:
Delphi-Quellcode:
Ich habe schon einiges probiert, allerdings füllt sich sie progressbar immer am Ende auf 100%, weil das ergebnis der Schleife natürlich am ende nur einmal ausgegeben wird (nämlich, dass er fertig mit schreiben ist), die Zwischenergebnisse, die jetzt wichtig für die progressbar sind bekomme irgendwie nicht aus dieser schleife raus :wall:
progressbarX.max := gesamte schreibvorgänge;
progressbarX.stepby (1); progressbarX.stepit; // balken wird bei jeden schreibvorgang um '1' weiter geschoben; ich habs auch schon mit einem Timer versucht, hat aber auch nicht so richtig gefunzt folgende befehle, fällt mir gerade ein hab ich auch schon probiert, naja.. also entweder an die falsche Stelle geschrieben, oder... naja hier die befehle:
Delphi-Quellcode:
Jemand ne Idee? ich glaub auch ich habs fast richtig, aber irgendwie fehlt noch der letzte, entscheidene Geistesblitz (oder auch nicht :D):gruebel:
progressbarX.update;
application.processmessages; Vielen Dank schon mal! |
Re: Progressbar einbinden
Wie sieht denn die For-Schleife aus?
|
Re: Progressbar einbinden
also das ist jetzt nur die Schleife, wenn du mehr oder alles brauchst einfach sagen :):
Delphi-Quellcode:
for writerounds := 0 to filesize do
write (tf, '0'); //wobei 'tf' die Textfile ist closefile (tf); end |
Re: Progressbar einbinden
Das aktualisieren der ProgressBar muss in den Schleifenrumpf:
Delphi-Quellcode:
for writerounds := 0 to filesize do
begin write(tf, '0'); ProgressbarX.StepIt; Application.ProcessMessages; end; closefile(tf); |
Re: Progressbar einbinden
Danke! Hat gefunzt!
Ist jetzt aber sehr langsam geworden, lässt sich das vermeiden? |
Re: Progressbar einbinden
Aktualisiere die Progressbar nur bei jedem z.B. 10. Durchlauf, dann sollte das auch schneller gehen.
|
Re: Progressbar einbinden
Alles klar! Vielen Dank Leuzt!!
|
Re: Progressbar einbinden
Ich habe eine Schleife die ziemlich oft (im Testlauf 62 Mio. mal) durchlaufen wird und versuche gerade verschiedene Möglichkeiten die Progressbar nicht zu oft zu aktualisieren:
Durchlaufdauer im Testlauf ohne Progressbar : 14 Sek. PB aktualisieren mit: IF i AND $FF = 0 : 16 Sek. IF i AND $2000 = 0 : 52 Sek. IF i mod 1000 = 0 : 17 Sek. immer: : 79 Sek. Es wundert mich, dass "AND $2000" so langsam ist, aber ok. Und es wundert mich sehr, dass "AND $FF" so schnell ist, weil die Aktualisierung der ProgressBar in diesem Testlauf ca. 242.000 mal stattfindet. Kennt jemand noch bessere / elegantere Arten das zu lösen? (Timer ist mir irgendwie nicht sympatisch - mann muss die Zählvariable rüberkriegen und die Aktualisierung hat auch nicht funktioniert) |
Re: Progressbar einbinden
![]() Das Problem bei sowas ist: - Rechner sind unterschiedlich schnell - sie sind auch unterschiedlich ausgelastet - und durch verschiedene Faktoren ist auch die Schleife nicht immer gleich schnell früher versuchte man es so, daß man erstmal die geschwindigkeit des PCs gemessen hat, dann daraus sich berechnete, alle wieviel Tackte/Durchläufe man etwas machen mußte, damit es etwa dem Intervall entsprech, welches man wollte, aber - PCs sind heute auch nicht immer gleich schnell > vorallem da (nicht wie unter DOS) mehere Programme gleichzeitig laufen > und auch CPUs mal unterschiedlich getaktet sind (mein kleiner AMD ändert seinen Takt, je nach Auslastung) also bleibt nur Eines: immer schön und ständig erneut nachmessen und sich nicht an feste Werte halten, aber dennoch zeitlich unterschiedliche Werte, wie wie irgendwelche Durchlaufsanzahlen. [add] und was das Problem von razer91 angeht, also die Datei Byteweise befüllen zu wollen und auch nochjedes Byte einzeln anzuzeigen ... selbst der Tipp mit "10. Durchlauf" ist da nicht wirklich sinnvoll, da dieses immernoch NUR 10 Byte pro Schritt sind ... ist vollkommen "irre". heutige Festplatten schieben (wenn sie halbwegs richtig bediehnt werden) mehrere dutzend/hundert MB in der Sekunde durch und sowas geht nicht, wenn man sie nur mit so Kleinkram füttert. |
Re: Progressbar einbinden
Danke himitsu!
Die unterschiedlichen Rechnergeschwindigkeiten sind gar kein so grosses Problem. Wenn meine Progressbar ca. 5 mal pro Sekunde aktualisiert wird, dann ist das schon voll in Ordnung. Das Hauptproblem an der Sache ist, dass eine Schleife die SEHR oft durchlaufen wird (bei mir im 6-8 Stelligen Bereich) nicht ausgebremst wird. Da würde es sich wahrscheinlich sogar lohnen die Abfrage in ASM zu machen, nur hab ich seit dem 6502 kein ASM mehr gemacht :stupid: Folgendes hatte ich zuerst. Die Routine braucht 16 Sekunden (statt 14 ohne Progressbar).
Delphi-Quellcode:
Und jetzt 15 Sekunden (statt 14 ohne Progressbar):
PB1.Max := 100;
While MStream.position <> MStream.size Do Begin //machwas if (MStream.Position and $FF) = 0 then PB1.Position := 100 * MStream.Position div MStream.Size; End;
Delphi-Quellcode:
Funktioniert also beides sehr gut. Danke für den Tipp.
PB1.Max := 100;
Start := GetTickCount; While MStream.position <> MStream.size Do Begin //machwas if gettickcount - start >= 200 then begin PB1.Position := 100 * MStream.Position div MStream.Size; //application.processmessages; //nicht notwendig Start := GetTickCount; end; End; Nochmal zusammenfassend:
Delphi-Quellcode:
scheidet ganz aus. Ist extrem langsam. Ebenso wie - für mich überaschenderweise:
PB1.Max := MStream.Size;
While MStream.position <> MStream.size Do Begin //machwas PB1.stepit; End
Delphi-Quellcode:
Also eine der zwei Varianten oben verwenden und es läuft effizient.
While MStream.position <> MStream.size Do
Begin //machwas if (MStream.Position and $2000) = 0 then PB1.Position := 100 * MStream.Position div MStream.Size; End; |
Re: Progressbar einbinden
Zitat:
Delphi-Quellcode:
Denn wer sagt dir, daß ein Rechner für diese 65536 Durchgänge nicht 'ne Stunde braucht
for i := 1 to 2000000000 do
begin ... mach was if i and $ffff = 0 then Application.ProcessMessages; end; und ein anderer Rechner das nicht schon nach ein paar Millisekunden durch hat. Ergo kannst du schlecht sagen "noar, das sind grob so um die 5 Mal pro Sekunde". Zitat:
wenn nicht, - dann würde ich lieber < statt <> verwenden - und bei dem =0 könnte es vorkommen, daß einiges übersprungen wird. PS: hier du hast 'ne ProgressBar mit 100 Schritten if (MStream.Position and $ff) = 0 then und bei einer 1 MB-Datei (sozusagen 6-stellig) wird diese ProgressBar über 4000 Mal aktualisiert, das sind 40 Mal mehr, als sie überhaupt anzeigen kann. if (MStream.Position and $2000) = 0 then das ist für mich nicht überraschend ... immerhin ist das fast so schlimm wie if (MStream.Position and $1) = 0 then nur daß bei Letzterem jeden 2. Durchlauf etwas gemacht wird und bei Ersterem 8192 Mal hintereinander und dann 8192 Mal garnicht und so weiter ... also im Durchschnitt bei jedem 2. Durchlauf. versuch es mal so if (MStream.Position and $1fff) = 0 then |
Re: Progressbar einbinden
Hallo,
wenn es nur um die Aktualisierung der ProgressBar geht, dann wäre auch ein Refresh der Progressbar vorzuziehen als ein Application.ProcessMessages. Ausschließlich würde ich aber das nicht machen, da sonst die Application mehr oder weniger schläft. Ich habe es mal so gelöst, dass ich öfters die Progressbar aktualisiert habe als die Application selber. Das bringt spürbare Verbesserung. Vielleicht hilft dir das? Gruß Matze |
Re: Progressbar einbinden
Zitat:
$2000 = Bin 0010 0000 0000 0000 = 8192 $1FFF = Bin 0001 1111 1111 1111 = 8191 i AND $1FFF ist erst im 8192'sten Durchlauf gleich Null -> wie gewünscht. $1FFF oder auch $FFFF funktionieren perfekt. Das mit dem Aktualisieren werde ich mir anschauen, Matze. Danke für eure Hilfe. :thumb: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz