Autor Beitrag
fuba
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 125

Win7
D7 Ent.
BeitragVerfasst: 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:
ausblenden 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; // DoAbort = Globale Variable
    Dec(RemCount);
    Inc(TimeCount);
    Inc(c);
    WaitForSingleObject(Event, 1);
    //Sleep(1); // auch schon mit Sleep versucht
    if (c > 999then // Update nur jede sekunde
    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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: 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,


Zuletzt bearbeitet von Hidden am So 01.08.10 13:30, insgesamt 1-mal bearbeitet
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10184
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 01.08.10 13:23 
Moin!

Kann sein, du suchst sowas hier? :idea: :nixweiss:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 01.08.10 13:44 
user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
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)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 125

Win7
D7 Ent.
BeitragVerfasst: So 01.08.10 14:34 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin!

Kann sein, du suchst sowas hier? :idea: :nixweiss:

cu
Narses


hab es damit auch schon versucht, aber bei 1msec kommt das gleiche raus wie bei sleep.
(manchmal gehts, manchmal nicht)

user profile iconLuckie hat folgendes geschrieben Zum zitierten Posting springen:

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:
ausblenden 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; // DoAbort = Globale Variable
    Dec(RemCount);
    Inc(TimeCount); // TimeCount wird bei FormCreate auf 0 gesetzt, soll also gesamtzeit übergeben
    WaitForSingleObject(Event, 1000);

    // Update der Labels
    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



BeitragVerfasst: 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":

ausblenden 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, 125)+' msec');
  Application.ProcessMessages;
END;
end;
Einloggen, um Attachments anzusehen!
fuba Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 125

Win7
D7 Ent.
BeitragVerfasst: Mo 02.08.10 03:41 
Moderiert von user profile iconNarses: 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 :)