![]() |
Problem mit sleep
Hallo,
ich habe ein Programm geschrieben, welche alle zehn Millisekunden Daten an den Parallelport schickt, bzw. sollte. Die Übertragung an sich funktioniert zwar hervorragend, das mit der Zeit jedoch nicht. Ich schicke 983 Werte weg (mit je 10 ms Pause dazwischen ab). Anschließend kommt nochmal eine 10800 ms lange Pause. wenn ich nun die Zeit errechne, die er brauchen dürfte, und die mit der gemessenen vergleiche ergibt sich eine Differenz von bis zu 6000 ms. Zudem "hängt" bei sleep() das ganze Program. Kennt jmd. eine Lösung wie ich dieses "Zeitproblem" lösen kann? |
Re: Problem mit sleep
Sleep() wartet aktiv. Besser Delay() oder einem Hintergrund-Thread
|
Re: Problem mit sleep
Schau dir mal die Timer Komponente an...
|
Re: Problem mit sleep
Zitat:
|
Re: Problem mit sleep
Hallo,
mit der habe ich es auch schon probiert. Die ist (bei mir) aber noch ungenauer. Zwar wird das Fenster dann immer wieder neu gezeichnet, aber die Sache mit der Zeit ist bei mir im Moment wichtiger. @Dunkel: Das ist glaube ich ein wenig zu aufwendig für mein Ziel. :) Freue mich trotzdem über jede Idee! |
Re: Problem mit sleep
Zitat:
In Windows bekommt jeder Prozess n Millisekunden (irgendwo zwischen 10 und 20) der Zeitscheibe zugeteilt in der es machen kann was es möchte. Dann "würgt" Windows diesen Prozess ab und gibt dem nächsten Prozess Zeit etwas zu machen. In sofern kann ein Sleep nicht exakt 10 ms pausieren. Es gibt Aufsätze für Windows um zeitkritische Tasks zu erledigen. Zumindst habe ich vor einer Ewigkeit solch eine DLL (-Sammlung) gesehen. Erstens war sie nicht ganz billig, zweitens hege ich Zweifel an der Funktion; hat sich aber dennoch sehr interessant angehört. Leider komme ich nicht mehr auf den Namen... :gruebel: |
Re: Problem mit sleep
Zitat:
|
Re: Problem mit sleep
Sleep, Delay und TTimer verwenden intern GetTickCount und das hat aktuell eine Auflösung von 8-10ms ... bei so vielen kurzen Intervallen summieren sich die Fehler und es kommt zu solchen Differenzen.
Was willst du denn erreichen? für "genauere" Messungen/Intervalle im unteren Millisekundenbereich, müßtest du einen HighPerformeceCounter/-Timer verwenden. |
Re: Problem mit sleep
Zitat:
|
Re: Problem mit sleep
Timer habe ich ausprobiert. Delay ist doch sleep() oder?
Ich möchte mit dem Programm eine Maschine ansteuern welche das Rauchverhalten von Rauchern simuliert. Deswegen sind solche Ungenauigkeiten natürlich sehr schlecht. Gibt es denn nicht eine (kostenlose) Lösung für mein Problem? Ich werde mal ausprobieren was passiert, wenn ich die Priorität im Taskmanager auf Echtzeit setze. |
Re: Problem mit sleep
Zitat:
Zitat:
Zitat:
|
Re: Problem mit sleep
Zitat:
Zitat:
![]() |
Re: Problem mit sleep
schade,
die Priorität macht gar keinen Unterschied :( Das Tut werde ich mir mal ansehen. Danke! |
Re: Problem mit sleep
:wiejetzt:
wusste gar nicht, dass Raucher soooo schnell rauchen können. :shock: |
Re: Problem mit sleep
Zitat:
|
Re: Problem mit sleep
ne, nicht ganz :)
raucher atmen ein, da die Lunge organisch ist, geht das "stufenlos". Der PC kann es aber nicht ohne Stufen. Deshalb baue ich aus lauter Punkten eine Kurve zusammen, die dann wiederum dem Zug des Rauchers entspricht. :) Lustige Idee, oder? |
Re: Problem mit sleep
ich hab noch zwei neue Dinge rausgefunden:
Bei Priorität "Echtzeit" braucht das Programm minimal länger. Und auf meinem Laptop (2*1,6 GHZ) ist das ganze fast 5000 ms schneller als auf meinem Tower-Rechner (1*2,80 GHZ, 2 Threads). Auf beiden ist XP installiert (jedoch nicht das gleiche ServicePack) |
Re: Problem mit sleep
Zitat:
|
Re: Problem mit sleep
Was steuerst du denn an? Ich wüsste auch nicht dass der Parallelport so zeitgenau ist, selbst wenn es Windows könnte.
Hier musst du dringend Hardwaremäßig etwas dazwischenschalten. Dort kannst du dann deine Kurve hinterlegen und diese hintereinanderweg ausgeben. Läuft quasi auf die Idee des Microcontrolers hinaus. Denn nix anderes steckt dahinter. Sowas gibt es beispielsweise von National Instruments. Suche mal nach I/O Karten oder DA-Karten. Das steckst du dann in den PCI-Slot und (fast) fertig. |
Re: Problem mit sleep
Zitat:
Zitat:
Wie schon gesagt ... Windows (auch nicht Linux) ist [add]nicht[/add] für sehr zeitgenaue und schnelle Sachen ausgelegt. Lösungsen: siehe meine beiden Vorredner. |
Re: Problem mit sleep
Zitat:
Und, Windows ist durchaus auch für RealTime-Processing geeignet. Die ganze Embedded-Reihe ist AFAIK auf RealTime ausgelegt; muss es auch, daran hängen häufig komplexe Maschinen welche zeitkritisch arbeiten müssen/sollen. Linux kann ähnliches. Nur die ganzen EndUser-Editionen sind keinesfalls dafür geeignet (es sei denn man investiert ein paar Euronen), diese sind eher fürs Multitasking optimiert. |
Re: Problem mit sleep
Liste der Anhänge anzeigen (Anzahl: 1)
Ich bastele gerade mit D2 an einer präzisions Laufzeitsteuerung und muß festellen, das Windows (XP) sehr wohl im 1 MS Bereich arbeiten kann.
Wers nicht glaub, einfach mal den Anhang ausprobieren. Is noch nicht fertig, ich bastle wie gesagt gerade dran rum... |
Re: Problem mit sleep
Delphi-Quellcode:
procedure DelayQPC(t: cardinal);
var a, b: Int64; Begin QueryPerformanceFrequency(b); QueryPerformanceCounter(a); b := a + (b * t) div 1000000; //10 000 = 0.1ms, 100 000 = 0.01ms, 1 000 000 = 0.001ms While a < b do QueryPerformanceCounter(a); end; Aufruf: DelayQPC(1000); // 1 msec DelayQPC(10000); // 10 msec |
Re: Problem mit sleep
Mit einem Sleep, Delay oder gar DelayQPC bekommt man keine einheitlichen Intervalle hin.
selbst wenn sleep genauer wäre, würde dennoch das Intervall nicht stimmen.
Delphi-Quellcode:
macht also zusammen mehr als 30ms
mach was << das braucht auch Zeit
warte 10 ms mach was << dieses ebenfalls warte 10 ms mach was << und hier wieder warte 10 ms man müßte also, wenn schon, die Zeit ab einem festen Punkt aufrechnen
Delphi-Quellcode:
oder
Temp = Zeit;
mach was Temp + 10 ms warte bis Temp = Zeit mach was Temp + 10 ms warte bis Temp = Zeit mach was Temp + 10 ms warte bis Temp = Zeit Zitat:
Delphi-Quellcode:
beziehungsweise
Start = Zeit;
mach was warte x ms Temp = Zeit - Start Start = Zeit; mach was, das Temp ms später zum vorherigen Ereignis entspricht warte x ms Temp = Zeit - Start Start = Zeit; mach was, das Temp ms später zum vorherigen Ereignis entspricht warte x ms
Delphi-Quellcode:
Start := Zeit;
mach was warte x ms mach was, das (Zeit - Start) ms entspricht warte x ms mach was, das (Zeit - Start) ms entspricht warte x ms |
Re: Problem mit sleep
Hallo,
habe jetzt noch ein bisschen weiterentwickelt. Die Pause soll ja nach Ausgabe eines Wertes erfolgen, danach zeichnet das Programm aber noch einen Graphen. Ich nehme nun einmal die Zeit mit QueryPerfomanceCounter vorm Zeichnen und einmal danach. Die Differenz ziehe ich dann bei der Pause ab, welche ich mit einer Funktion ähnlich der Funktion von hathor realisiere. Ergebnis: Ich habe nun auf einem dritten Rechner (müsste eigentlich schlechter sein als die beiden anderen) eine Differenz von nur noch 37 ms festgestellt. Das Problem ist also gelöst! Vielen Dank! I love Delphi! Edit: Danke auch himitsu! Du hattest ja eigentlich die gleiche Idee wie ich :) |
Re: Problem mit sleep
Das was er braucht sollte über die Soundkarte möglich sein.
Einfach eine Wavedatei unendlich oft wiedergeben. Du must NUR einen Wandler haben der das auf RS232 umwandelt...eine Art MODEM vielleicht. |
Re: Problem mit sleep
Danke nochmal für alle Lösungen,
wenn ich Zeit habe, probiere ich das mit der Soundkarte vielleicht wirklich nochmal aus! :) I love Delphi! |
Re: Problem mit sleep
Liste der Anhänge anzeigen (Anzahl: 2)
Die Auflösung des "normalen" Timers kann man sich auch anzeigen lassen:
.
Delphi-Quellcode:
Bei mir (WIN XP,Notebook) werden 15.620 msec angezeigt:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabel; procedure FormCreate(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; type msecs = real; implementation {$R *.dfm} function resolution: msecs; var t0 : tdatetime; begin t0 := now; while now = t0 do ; result := msecsperday * (now -t0); end; function Strip(L,C:char;Str:string):string; {L is left,center,right,all,ends} var I : byte; begin Case Upcase(L) of 'L' : begin {Left} while (Str[1] = C) and (length(Str) > 0) do Delete(Str,1,1); end; 'R' : begin {Right} while (Str[length(Str)] = C) and (length(Str) > 0) do Delete(Str,length(Str),1); end; 'B' : begin {Both left and right} while (Str[1] = C) and (length(Str) > 0) do Delete(Str,1,1); while (Str[length(Str)] = C) and (length(Str) > 0) do Delete(Str,length(Str),1); end; 'A' : begin {All} I := 1; repeat if (Str[I] = C) and (length(Str) > 0) then Delete(Str,I,1) else I := succ(I); until (I > length(Str)) or (Str = ''); end; end; Strip := Str; end; {Strip} function RealToStr(Number:extended;Decimals:byte):string; var Temp : string; const Floating = 255; begin Str(Number:20:Decimals,Temp); repeat if copy(Temp,1,1) = ' ' then delete(Temp,1,1); until copy(temp,1,1) <> ' '; if Decimals = Floating then begin Temp := Strip('R','0',Temp); if Temp[Length(temp)] = '.' then Delete(temp,Length(temp),1); end; RealToStr := Temp; end; {RealToStr} function avgres : real; var j : integer; begin result := 0; for j := 1 to 100 do result := result + resolution; result := result /100; end; procedure TForm1.FormCreate(Sender: TObject); begin Label1.Caption:=' Average resolution = '+ RealToStr(avgres,3)+' msecs'; end; end. das heisst also: ein Sleep(16) ist der niedrigste, sinnvolle Wert. Bei hoher Belastung der CPU steigt der Wert deutlich an - siehe Anhang: Sleep(0) dauert 0,010msec, aber: Bei hoher Belastung der CPU steigt der Wert von Sleep(0) deutlich an - bis fast 50 msec- siehe Anhang: |
Re: Problem mit sleep
Nur zur Information - siehe oben:
Sleep(0) dauert 0,010msec, aber: Bei hoher Belastung der CPU steigt der Wert von Sleep(0) deutlich an - bis fast 50 msec- siehe Anhang oben. Nachtrag: Wahrscheinlich ist mir bei der Berechnung des Sleep(0)-Wertes ein Denkfehler unterlaufen, denn ich habe den Wert von "Resolution" abgezogen: Gemessen: Resolution: 15,620 msec Sleep(0): 15,630 msec Wert(Sleep(0)) - Wert(Resolution) = Sleep0 (=vermutlich falsch!!!) Was ist Euere Meinung? |
Re: Problem mit sleep
du mußt bedenken, daß die Dauer bedingt durch die Messung nie immer genau gleich sein kann.
z.B. wenn GetTickCount eine Taktrate von 8ms hat, dann wäre die Dauer von Sleep(0) bis Sleep(7) Gundsätzlich erstmal gleich, aber dazu kommt noch der Zeitpunkt wo man das Sleep bzw die Messung startet.
Delphi-Quellcode:
Zeit Wert von Start Start
in ms GetTickCount Sleep(1..8) Sleep(9..16) + Dauer + Dauer 0 0 # # 1 0 . . 2 0 . . 3 0 . # . 4 0 . . . 5 0 . . . 6 0 . . . # 7 0 . . # . . 8 1 . . . . . . 8ms 6ms 1ms . . 9 1 . . 10 1 . . 11 1 . . 12 1 . . 13 1 . . 14 1 . . 15 1 . . 16 2 . . . . . . . . . . . . 16ms 10ms 17 2 18 2 |
Re: Problem mit sleep
Durch "while now = t0 do ; " wird ein definierter Zeitpunkt erzeugt.
Das gilt aber nur für obige Tests. In der Realität wird aber Sleep() "zufällig" eingesetzt - dann hast Du natürlich recht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:07 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