| Autor |
Beitrag |
fuba
      
Beiträge: 125
Win7
D7 Ent.
|
Verfasst: So 01.08.10 12:24
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
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: 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.
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,
Zuletzt bearbeitet von Hidden am So 01.08.10 13:30, insgesamt 1-mal bearbeitet
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: So 01.08.10 13:23
Moin!
Kann sein, du suchst sowas hier?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: 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.
Für diesen Beitrag haben gedankt: Andreas L., Hidden
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: 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*
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
fuba 
      
Beiträge: 125
Win7
D7 Ent.
|
Verfasst: 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
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?
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: 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; |
Einloggen, um Attachments anzusehen!
|
|
fuba 
      
Beiträge: 125
Win7
D7 Ent.
|
Verfasst: Mo 02.08.10 03:41
Moderiert von Narses: Komplett-Zitat des letzten Beitrags entfernt.
werd ich mir mal beiseite legen,danke
ach ja, wie es aussieht funktioniert die übergabe von sekunden, frage also beantwortet.
Danke an alle 
|
|
|