Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Zeitschleife
Tilman - Do 08.11.07 20:59
Titel: Zeitschleife
Hallo,
Ich brauche für eine Anwendung eine Schleife die auf verschiedenene Rechner möglichst gleichschnell läuft. Die Schleife läuft in einem eigenen Thread. Das Problem ist dass die Schleife aber auch möglichst schnell laufen soll (am besten sollte der Benutzer selber wählen können wie schnell die Schleife ist).
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:
| procedure TMyOwnThread.Execute; var t: integer; o: Integer; begin try t := gettickcount; o := 0; repeat inc(o); if (t+0 < gettickcount) then begin t := gettickcount; form1.Label2.Caption := IntToStr(o); o := 0; if links then mouse_event(MOUSEEVENTF_MOVE,4294967290,0,0,0); if oben then mouse_event(MOUSEEVENTF_MOVE,0,4294967290,0,0); end;
until application.Terminated; except end; end; |
Das Problem ist: obwohl mit (t+0) auf den geringstmöglichen Wert gestellt ist, läuft die Schleife wesentlich langsamer als ohne "Bremse". Mit o gemessen erhalte ich ca. 20.000 "übersprungene" Durchläufe. Gibt es ein feineres Verfahren als getTickCount?
Die Prozessorauslastung geht dabei auf 100%, was z.B, auf meinem Laptop die Auswirkung hat dass der Lüfter anspringt. Um dies zu Vermeiden benutze ich in älteren Versionen meines Programms die Zeile sleep(1), mit der die Auslastung deutlich verringert wird. Gibt es dazu eine Alternative?
oldmax - Fr 09.11.07 07:57
Hi
Mir scheint, dein Ansatz ist falsch. Was machst du eigentlich mit der Variable o ? Du setzt diese auf 0, ok. Du incrementierst o in der Schleife und schreibst das in Label2. Dann setzt du wieder auf 0.
Soweit, so gut, aber wofür ?
Da ich mit GetTickCount bisher nicht gearbeitet habe, kann ich nur vermuten, das ich eine Zahl zurückbekomme.
Wenn ich nun Schleifendurchläufe mit gettickcount steuern möchte, so sollte die Schleife so aufgebaut sein ( ungeprüft ):
Delphi-Quelltext
1: 2: 3: 4:
| t:=Gettickcount+o; Repeat ..... until t<=Gettickcount; |
Übrigends, es ist besser du benutzt etwas aussagekräftigere Variablennamen. "o" , das dürfte dir jetzt auch klar sein, ist sehr leicht mit 0 verwechselt und da der Compiler das völlig ok findet, ist die Überraschung erst zur Laufzeit festzustellen. Dann such mal in einem Programm mit teilweise komplizierten Zeilenstrukturen, warum deine Rechnung nicht stimmt....
Gruß oldmax
//Edit: Sorry, verfgiß den Text, hab jetzt erst dein Problem erkannt....
alzaimar - Fr 09.11.07 09:38
Wieso benutzt Du nicht die Suchfunktion. Das GetTickCount nur auf xx ms genau geht, wäre Dir dann irgendwie aufgefallen. Alternativ gibt es noch soetwas wie 'F1'. Aber ich sehe gerade, das Du noch mit D3 und D7 arbeitest, und da ist die Hilfe ungenau...
Google ist auch ganz nett. Da findest Du dann an 2. oder 3.Stelle das hier:
http://msdn2.microsoft.com/en-us/library/ms724408.aspx
jaenicke - Fr 09.11.07 10:33
Titel: Re: Zeitschleife
Tilman hat folgendes geschrieben: |
Das Problem ist dass die Schleife aber auch möglichst schnell laufen soll. |
Das widerspricht deinem Quelltext... Du benutzt try..except als Bremse,
aber die Schleife soll möglichst schnell sein. :nixweiss:
Dadurch, dass du auf den Label etwas ausgibst, bremst du im if nochmal. Visuelle Komponenten solltest du in zeitkritischen Prozessen am besten gar nicht ansprechen, weil dies stark bremst.
Zudem ist es sowieso ein Fehler, dass du aus einem Thread heraus ohne Synchronisierung eine Komponente der VCL ansprichst, denn diese sind nicht threadsicher. Das darf man nie machen.
Jedenfalls gibt es QueryPerformanceCounter, was sehr viel genauer als GetTickCount ist. Da findest du für Delphi auch leicht Beispiele.
Tilman - Fr 09.11.07 17:57
Okay danke erstmal... mit QueryPerformanceCounter funzt es.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| procedure TMyOwnThread.Execute; var t,n: int64; begin try QueryPerformanceCounter(t); repeat QueryPerformanceCounter(n); if (t +10000 < n) then begin QueryPerformanceCounter(t); if not (rdown[1] or rdown[2] or rdown[3] or rdown[4]) then sleep(100); if rdown[1] then mouse_event(MOUSEEVENTF_MOVE,cardinal(-5),0,0,0); if rdown[2] then mouse_event(MOUSEEVENTF_MOVE,0,cardinal(-5),0,0); if rdown[3] then mouse_event(MOUSEEVENTF_MOVE,5,0,0,0); if rdown[4] then mouse_event(MOUSEEVENTF_MOVE,0,5,0,0); end;
until application.Terminated; except end; end; |
Wie ihr sehen könnt hab ich auch für sleep ne lösung gefunden... gesleept wird jetzt nur noch wenn die Schleife sich im "Ruhezustand" befindet, also wenn sie eigentlich nicht benötigt wird.
@oldmax: was o angeht hab ich doch alles im ersten Post beschrieben... es handelte sich um eine Debugging-Konstruktion zum testen der Geschwindigkeit, sprich ich wollte wissen ob die Funktion so lahm ist wegen meinem Code oder weil getTickCount so ungenau ist. Ergebnis: ca. 25.000 ausgelassene Schleifendurchläufe... wie gesagt ;-)
@alzaimar: dein Post hat mir leider nicht weitergeholfen.
@jaenicke: Danke für den Hinweis auf QueryPerformanceCounter, die funktion kannte ich wirklich noch nicht und sie ist hier die Lösung :zustimm:
Allerdinsg, nur zu deiner Information: try..except dient dazu eventuell auftretende Fehler abzufangen. Als "Bremse" wurde hingegen die Systemzeit bzw. der sleep-Befehl verwandt.
TProgger - Fr 09.11.07 18:04
Zur Erläterung: try .. except veranlasst den Compiler, an dieser Stelle zusätzlichen Code in die EXE zu bauen, dessen Abarbeitung dann auch deutlich langsamer ist. Das war wohl mit Bremse gemeint.
jaenicke - Fr 09.11.07 19:06
Ja, das mit der Bremse war ironisch gemeint ;-). try..except verlangsamt schon deutlich, und deshalb sollte man schon so wenig wie möglich Code da hineinpacken. Und wo sollte denn da ein Fehler auftreten? Der einzige Fehler, der mir so einfällt, wäre als du den Zugriff auf das Label noch drinne hattest, da kann sowas mal passieren.
alzaimar - Fr 09.11.07 20:09
Tilman hat folgendes geschrieben: |
@alzaimar: dein Post hat mir leider nicht weitergeholfen. |
Kein Wunder, Du hast ihn auch nicht verstanden.
Tilman - Fr 09.11.07 20:16
alzaimar hat folgendes geschrieben: |
Tilman hat folgendes geschrieben: |
@alzaimar: dein Post hat mir leider nicht weitergeholfen. |
Kein Wunder, Du hast ihn auch nicht verstanden. |
Da magst du recht haben. Ich habs mir nochmal durchgelesen, denke du wolltest mir den Wink geben mal nach
multimedia timer und
high-resolution timer zu fahnden, muss aber sagen das mein Englisch nich sooo pralle ist, daher hab ich das gelassen. Aber es funzt ja jetzt auch so.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!