Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wird auf procedure gewartet ? (https://www.delphipraxis.net/163940-wird-auf-procedure-gewartet.html)

Blamaster 22. Okt 2011 20:45

Delphi-Version: 7

Wird auf procedure gewartet ?
 
Hi,

folgendes Frage. Mal angenommen ich habe diese for Schleife:

Code:
for i := 1 to 3 do
begin
  SendeDaten(i);
end;
SendeDaten ist dabei eine Procedure geladen aus einer dll.
Die schleife selber steckt im OnTimer Event eines Timers mit einem 20ms Intervall.

Nun folgende Frage. Innerhalb der for Schleife wird ja immer solange gewartet bis die procedure SendeDaten fertig ist.
Was würde jetzt passieren, wenn der in der procedure abzufertigende Code länger dauert als die 20ms vom Timerintervall ?

Gruß Yannic

himitsu 22. Okt 2011 21:26

AW: Wird auf procedure gewartet ?
 
Der Timer läuft über Messages innerhalb des Hauptthreads (der VCL) und in einem Thread kann natürlich immer nur einwas gleichzeitig abgearbeitet werden.
Also ja, es wird gewartet. (vermutlich)

Ausnahme: Man/Etwas ruft irgendwo
Delphi-Quellcode:
Application.ProcessMessages;
auf und verarbeitet zwischendurch die anderen anfallenden Messages.


Tipp: Warum hast du es nicht einfach mal selber ausprobiert?
Einfach mehr Schleifendurchläufe ausführen. :roll:

Da wir nicht wissen was SendeDaten macht (hat und wieder einmal keiner verraten), können wir keine genaue Antwort geben.

Medium 23. Okt 2011 01:41

AW: Wird auf procedure gewartet ?
 
Ad 1: Es kommt auf die Implementierung von SendeDaten() an. Wird dort ein Workerthread pro Aufruf mit dem eigentlichen Senden beauftragt, wird nicht zwangsweise bis zum tatsächlichen Abschluss des Sendens gewartet. (Synchron versus Asynchron, um mal Schlagworte zu liefern)
Ad 2: Trifft ein Timer-Event (bzw. irgendein Event) ein, während der Verarbeiter (dein Formular z.B.) beschäftigt ist, kommt er in eine Warteschlange. Die nimmt imho aber auch nur begrenzt Messages auf (Message-Queue heisst das Teil), wonach die Events verworfen werden. Deine Timer-Prozedur wird nicht mehrfach parallel aufgerufen, aber deine 20ms sind in Gefahr (welche ohnehin schon nah der Untergrenze der Schnelligkeit von Timern sind, wodurch die ohnehin schon recht fragwürdig sind).

Fazit: Ohne mehr Infos zu SendeDaten() kann man nicht mehr sagen.

Sir Rufo 23. Okt 2011 02:51

AW: Wird auf procedure gewartet ?
 
Zitat:

Zitat von Medium (Beitrag 1131939)
Ohne mehr Infos zu SendeDaten() kann man nicht mehr sagen.

Zitat:

Zitat von Blamaster (Beitrag 1131912)
Nun folgende Frage. Innerhalb der for Schleife wird ja immer solange gewartet bis die procedure SendeDaten fertig ist.

Ohne die
Delphi-Quellcode:
procedure SendeDaten
zu kennen kann hier nur ein ja kommen.
Denn
Delphi-Quellcode:
SendeDaten
wird im HauptThread abgearbeitet, und der arbeitet erst weiter, wenn eben 3x
Delphi-Quellcode:
SendeDaten
durchlaufen wurde.

Ich bin aber völlig bei dir, dass ein Timer mit 20ms mehr als fragwürdig ist ;)
Vor allem weil die Gefahr besteht, dass der Timer die Warteschlange so vollmüllen wird, dass die Anwendung einfach immer nur das TimerEvent aufrufen wird :mrgreen:

Ein mögliche (nicht schöne aber besser laufende) Lösung ist den Timer für die Dauer der Verarbeitung ausser Gefecht zu setzen
Delphi-Quellcode:
MySendTimer.Enabled := False;
try
  for i := 1 to 3 do
  begin
    SendeDaten( i );
  end;
finally
  MySendTimer.Enabled := True;
end;
Noch besser wäre es, das in einen Thread zu packen:
Delphi-Quellcode:
procedure TMySendThread.Execute;
begin
  while not Terminated do
  begin

    for i := 1 to 3 do
    begin
      SendeDaten( i );
    end;

    if not Terminated then
      // wirklich schlafen wird der nicht ;o)
      // aber er ist halt stets bemüht
      Sleep( 20 );
  end;
end;

p80286 23. Okt 2011 06:13

AW: Wird auf procedure gewartet ?
 
Der Timer generiert alle 20 ms eine Message, die auch abgearbeitet werden will.
Also 500 Schleifenaufrufe pro sec.
Da wird nichts vergessen oder uberholt oder ...

Worauf willst Du denn hinaus?
Ich habe den Eindruck, Du bist auf dem besten weg Dir selbst ein Beinzu stellen.

Gruß
K-H

himitsu 23. Okt 2011 09:11

AW: Wird auf procedure gewartet ?
 
Timer-Messages sind niederwertig und ich glaub es ist immer nur maximal Eine in der MessageQueue vorhanden ... ist also die selbe Message schonmal drin, wird keine Neue eingetragen.

Bei Start der Ausführung des Timer-Ereignisses wird die aktuelle Message aus der Queue abgefrag und gelöscht.
Wärend der abarbeitung fällt also maximal nur eine weitere Message an, welche auf die nächste Bearbeitung wartet.


[add]
Einen Timer mit einem Intervall von 100 ms.
Delphi-Quellcode:
var
  TimerStart, LastTimer, TimerCalls: Cardinal;

procedure TForm8.Timer1Timer(Sender: TObject);
begin
  if TimerStart = 0 then begin
    TimerStart := GetTickCount;
    LastTimer := TimerStart;
  end;
  Inc(TimerCalls);
  mnQueryText.Lines.Add(Format('%d  %.2n  %.2n',
    [TimerCalls, (GetTickCount - TimerStart) / 1000, (GetTickCount - LastTimer) / 1000]));
  LastTimer := GetTickCount;
  if TimerCalls = 100 then begin
    mnQueryText.Lines.Add('start');
    Sleep(10000);
    mnQueryText.Lines.Add('ende');
  end;
  if TimerCalls = 300 then
    Timer1.Enabled := False;
end;
Würden Ereignisse parallel ablaufen, dann würden Diese zwischen Start und Ende stehen.
Würden sich Ereignisse ansammeln/aufhäufen, dann würden nach dem Ende 100 Einträge (Pause durch Intervall) ganz schnell auftachen, da sie alle abgearbeitet würden.

Und zugleich sieht man, daß diese Timer relativ ungenau sind, denn die Zeit läuft dem Zähler voraus,
da der Zähler der Zeitanzeige hinterherläuft.
Würde es synchron/genau laufen, wäre ja die Zeit immer etwa ein Zehntel des Zählers.


Alternativ mal statt
Delphi-Quellcode:
    Memo1.Lines.Add('start');
    Sleep(10000);
    Memo1.Lines.Add('ende');
Folgendes ausprobieren.
Delphi-Quellcode:
    Memo1.Lines.Add('start');
    for i := 1 to 200 do begin // 200 * 50 = 10000
      Sleep(50);
      Application.ProcessMessages;
    end;
    Memo1.Lines.Add('ende');


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:36 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