Entwickler-Ecke
Windows API - Sleep 1msec in schleife problem (nicht immer)
fuba - So 01.08.10 12:24
Titel: Sleep 1msec in schleife problem (nicht immer)
hi leute,
habe mir eine procedure gebaut, welche mir ermöglichen soll, ein "sleep" zu unterbrechen bzw es werden während des Sleep 2 Labels Updated.
meien procedure:
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:
| procedure MySleep(aMSecDelay: integer); var i, c: integer; Event: THandle; begin c:=0; Event := CreateEvent(nil, False, False, nil); RemCount:=aMSecDelay; From1.Label2.Caption:=SecToDMS(RemCount div 1000); for i:=1 to aMSecDelay do begin Application.ProcessMessages; if DoAbort then break; Dec(RemCount); Inc(TimeCount); Inc(c); WaitForSingleObject(Event, 1); if (c > 999) then begin Form1.Label1.Caption:=SecToDMS(TimeCount div 1000); From1.Label2.Caption:=SecToDMS(RemCount div 1000); c:=0; end; end; end; |
wie ihr sehr, habe ich es schon mit sleep und WaitForSingleObject versucht, jedoch bei beiden das gleiche problem.
Das komische ist, manchmal (nicht immer) werden die Labels 1x Pro sekunde Updated (wie gewollt) und dann wieder 1x alle 3-5 sekunden.
Was mache ich falsch?
Hidden - So 01.08.10 13:09
Hi :)
Offensichtlich, macht Windows im Hintergrund noch andere Sachen. Auf jeden Fall kann ich dir aber sagen, dass zumindest Sleep() - so wie auch ein Timer - keine Zeitintervalle unter 50ms schafft, das hängt bereits auf Betriebssystem-Ebene. Die Wartezeit sollte also meines Wissens zumindest mit Sleep nie stimmen. :gruebel:
Wichtig zu wissen ist, dass Sleep() die Recourcen trotzdem verbraucht, sie also auch anderen Anwendungen nicht zur Verfügung stehen :!: (Stichwort "busy waiting"). Deshalb verwendet man meißtens einen TTimer bzw. die der TTimer-Klasse zu grunde liegende WinMessage, und Sleep() eher mal aus Bequemlichkeit.
lg,
Delete - So 01.08.10 13:44
Hidden hat folgendes geschrieben : |
| Auf jeden Fall kann ich dir aber sagen, dass zumindest Sleep() - so wie auch ein Timer - keine Zeitintervalle unter 50ms schafft, |
Das stimmt nicht. Ein Sleep(n) führt dazu dass der Thread den Rest der verbleibenden Zeitscheibe an das System abgibt, wenn n kleiner ist als die Länge einer Zeitscheibe. Eine Zeitscheibe ist unter Windows ca. 22. Millisekunden lang. Das heißt für 22 Sekunden bekommt der Thread Rechenzeit auf der CPU zugeteilt. Ist n kleiner als 22 Millisekunden gibt der Thread den Rest seiner Zeitscheibe an das System ab.
| Zitat: |
| Wichtig zu wissen ist, dass Sleep() die Recourcen trotzdem verbraucht, sie also auch anderen Anwendungen nicht zur Verfügung stehen |
Genau das tut Sleep nicht. Wie schon oben erwähnt gibt es den Rest der verbleiben Zeitscheibe ab und verbraucht somit auch keinerlei Ressourcen.
Die 50 Millisekunden Untergrenze gilt nur für Timer-Nachrichten und auch nur unter Windows 95, 98 und Millenium. Unter NT und höher beträgt der Wert ca. 15 Millisekunden oder so.
Und während Sleep Code ausführen zu wollen kann nicht funktionieren, da der Thread seine Rechenzeit abgibt und somit keinen Code ausführen kann. Der Thread kann erst wieder Code ausführen, wenn er wieder im zuteilungsfähigen Zustand versetzt wird nach dem Sleep und dann wieder an der Reihe ist und Rechenzeit zugeteilt bekommt.
Xion - So 01.08.10 14:10
Was du machen kannst ist, du verwendest einen Timer und guckst per GetTickCount wieviel Zeit denn tatsächlich vergangen ist. Das funktioniert natürlich nur für größere Intervalle, so dass die "Quantelung"(15ms wie oben geschrieben) der Timer-Events nicht ins Gewicht fällt (also vielleicht so ab 150ms).
Vielleicht gäbs da auch noch ne Möglichkeit mit OnIdle *in die Runde werf*
fuba - So 01.08.10 14:34
hab es damit auch schon versucht, aber bei 1msec kommt das gleiche raus wie bei sleep.
(manchmal gehts, manchmal nicht)
Luckie hat folgendes geschrieben : |
Und während Sleep Code ausführen zu wollen kann nicht funktionieren, da der Thread seine Rechenzeit abgibt und somit keinen Code ausführen kann. Der Thread kann erst wieder Code ausführen, wenn er wieder im zuteilungsfähigen Zustand versetzt wird nach dem Sleep und dann wieder an der Reihe ist und Rechenzeit zugeteilt bekommt. |
jop, deswegen wollte ich msecDelay auch in ner schleife mit sleep(1) durchlaufen.
nur wusste ich nicht, dass an sleep nicht so niedrige werte übergeben werden sollen :D
wenn ich also bei meinem MySleep nur sekunden übergebe, also msec div 1000, würde es also klappen?
also so:
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 MySleep(aSecDelay: integer); var i: integer; Event: THandle; RemCount: integer; begin Event := CreateEvent(nil, False, False, nil); RemCount:=aSecDelay; From1.Label2.Caption:=SecToDMS(RemCount); for i:=1 to aSecDelay do begin Application.ProcessMessages; if DoAbort then break; Dec(RemCount); Inc(TimeCount); WaitForSingleObject(Event, 1000);
Form1.Label1.Caption:=SecToDMS(TimeCount); From1.Label2.Caption:=SecToDMS(RemCount); end; end; |
Falls ich das richtig verstanden habe, solle man an sleep bei NT Systemen keinen kleineren wert als ~30msec angeben, richtig?
Delete - So 01.08.10 15:25
Mit folgendem Code kannst Du herausfinden, was Dein BS (WIN XP, WIN732, WIN764) auf der vorhandenen Hardware (Solo,Duo) bei Sleep() an Zeit "verbraucht":
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.Button1Click(Sender: TObject); var a, b, c: Int64; r: real; i: Integer; begin For i:=0 to 20 do BEGIN QueryPerformanceFrequency(a); QueryPerformanceCounter(b); Sleep(i); QueryPerformanceCounter(c); r:= (c - b) * 1000 / a; Memo1.lines.add('Sleep('+IntToStr(i)+') = '+ FloatToStrF(r, ffFixed, 12, 5)+' msec'); Application.ProcessMessages; END; end; |
fuba - Mo 02.08.10 03:41
Moderiert von
Narses: Komplett-Zitat des letzten Beitrags entfernt.
werd ich mir mal beiseite legen,danke :D
ach ja, wie es aussieht funktioniert die übergabe von sekunden, frage also beantwortet.
Danke an alle :)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 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!