Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Problem mit sleep (https://www.delphipraxis.net/130060-problem-mit-sleep.html)

I love Delphi 2. Mär 2009 18:52


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?

mkinzler 2. Mär 2009 18:55

Re: Problem mit sleep
 
Sleep() wartet aktiv. Besser Delay() oder einem Hintergrund-Thread

Forlan 2. Mär 2009 18:56

Re: Problem mit sleep
 
Schau dir mal die Timer Komponente an...

Dunkel 2. Mär 2009 18:57

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
Kennt jmd. eine Lösung wie ich dieses "Zeitproblem" lösen kann?

Z.B. ein Echtzeitbetriebssystem benutzen. Windows ist keins, zeitkritische Aufgaben sind nahezu nicht handlebar.

I love Delphi 2. Mär 2009 19:00

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!

Dunkel 2. Mär 2009 19:07

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
@Dunkel: Das ist glaube ich ein wenig zu aufwendig für mein Ziel. :)

OK, was ist denn Dein Ziel?

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:

Whatever 2. Mär 2009 19:11

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
mit der habe ich es auch schon probiert.

Womit? Timer oder Delay?

himitsu 2. Mär 2009 19:15

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.

Uwe Raabe 2. Mär 2009 19:56

Re: Problem mit sleep
 
Zitat:

Zitat von himitsu
für "genauere" Messungen/Intervalle im unteren Millisekundenbereich, müßtest du einen HighPerformeceCounter/-Timer verwenden.

...und das Ganze auch noch in einem Thread laufen lassen, der möglichst hohe Priorität hat. Die Aufgabe ist alles andere als trivial. Die Addons für Windows, die sowas einigermaßen stabil unterstützen kosten alle mehrere Hekto-€ und haben eine enorme Lernschwelle.

I love Delphi 2. Mär 2009 19:59

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.

himitsu 2. Mär 2009 20:08

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
Delay ist doch sleep() oder?

Delay ist Sleep+Application.ProgressMessages

Zitat:

Zitat von I love Delphi
Gibt es denn nicht eine (kostenlose) Lösung für mein Problem?

Ein kleiner Microcontroler, welcher den Anforderungen entspricht.

Zitat:

Zitat von I love Delphi
Ich werde mal ausprobieren was passiert, wenn ich die Priorität im Taskmanager auf Echtzeit setze.

dann legst du womöglich das ganze Windows lahm.

mkinzler 2. Mär 2009 20:09

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
Timer habe ich ausprobiert. Delay ist doch sleep() oder?

Nein.
Zitat:

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.
Dadurch erhöhst du die Auflöungsgenauigkeit auch nicht.
http://blubplayer.de/tutorials/TimerTutorial.pdf

I love Delphi 2. Mär 2009 20:12

Re: Problem mit sleep
 
schade,
die Priorität macht gar keinen Unterschied :(

Das Tut werde ich mir mal ansehen.

Danke!

thkerkmann 2. Mär 2009 20:15

Re: Problem mit sleep
 
:wiejetzt:
wusste gar nicht, dass Raucher soooo schnell rauchen können.
:shock:

mkinzler 2. Mär 2009 20:19

Re: Problem mit sleep
 
Zitat:

Zitat von thkerkmann
:wiejetzt:
wusste gar nicht, dass Raucher soooo schnell rauchen können.
:shock:

Ja und der Verbrauch wird in der Einheit Stangen/Sekunde gemessen :stupid:

I love Delphi 2. Mär 2009 20:21

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?

I love Delphi 2. Mär 2009 20:26

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)

Cyf 2. Mär 2009 20:36

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
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?

Wäre es nicht einfacher die Kurve zu approximieren?

sirius 2. Mär 2009 20:59

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.

himitsu 2. Mär 2009 21:04

Re: Problem mit sleep
 
Zitat:

Zitat von I love Delphi
Und auf meinem Laptop (2*1,6 GHZ) ist das ganze fast 5000 ms schneller

hier kann Windows die Thread auf die beiden CPUs verteilen

Zitat:

Zitat von I love Delphi
als auf meinem Tower-Rechner (1*2,80 GHZ, 2 Threads).

hier muß es ständig zwischen den Threads hin- und herschalten.

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.

Dunkel 2. Mär 2009 22:38

Re: Problem mit sleep
 
Zitat:

Zitat von himitsu
Wie schon gesagt ... Windows (auch nicht Linux) ist nicht für sehr zeitgenaue und schnelle Sachen ausgelegt.

Ich habe das Zitat korrigiert, könnte sonst verwirren.

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.

Sunlight7 3. Mär 2009 01:34

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...

hathor 3. Mär 2009 07:51

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

himitsu 3. Mär 2009 08:54

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:
mach was << das braucht auch Zeit
warte 10 ms

mach was << dieses ebenfalls
warte 10 ms

mach was << und hier wieder
warte 10 ms
macht also zusammen mehr als 30ms

man müßte also, wenn schon, die Zeit ab einem festen Punkt aufrechnen
Delphi-Quellcode:
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
oder
Zitat:

Zitat von Cyf
Wäre es nicht einfacher die Kurve zu approximieren?

Delphi-Quellcode:
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
beziehungsweise
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

I love Delphi 3. Mär 2009 09:32

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 :)

QuickAndDirty 3. Mär 2009 09:44

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.

I love Delphi 3. Mär 2009 12:41

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!

hathor 3. Mär 2009 14:48

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:
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.
Bei mir (WIN XP,Notebook) werden 15.620 msec angezeigt:
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:

hathor 4. Mär 2009 07:41

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?

himitsu 4. Mär 2009 09:16

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

hathor 4. Mär 2009 11:57

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 23:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz