Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi wait prozedur bewirkt vollständige cpu auslastung (https://www.delphipraxis.net/79483-wait-prozedur-bewirkt-vollstaendige-cpu-auslastung.html)

JonnyGuitar 23. Okt 2006 15:43


wait prozedur bewirkt vollständige cpu auslastung
 
tach zusammen,

ich benutze in einem service folgende wait prozedure:

Delphi-Quellcode:
procedure wait;
var
  res   : Cardinal;
  s     : String;
begin
  repeat
    Res := MsgWaitForMultipleObjects(2, hndlArr, false, 3600000, QS_ALLINPUT);

    if (Res = $ffffffff) then RaiseLastOSError;
    if Res = 1 then ForceUpdate := true;

    s := IntToStr(Res);
  until (Res = WAIT_OBJECT_0) or
        (Res = WAIT_TIMEOUT) or
        (Res = 1);
end;
diese schluckt aber leider 100% cpu last. was habe ich falsch gemacht?
ich hoffe einige leute haben verbesserungsvorschläge :)

ps: res = 1 tritt auf, wenn eins der beiden events aus dem handlearray ausgelöst werden

mfg Jonny

shmia 23. Okt 2006 17:20

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Du hast den Code unterschlagen, der das Array hndlArr befüllt.
Hat der Service eine Benutzeroberfläche? Falls nicht, gibt es keinen Grund für QS_ALLINPUT.

TurboMartin 23. Okt 2006 17:48

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Bringt in der Schleife viellecht ein Application.ProcressMessages was? :gruebel:

xaromz 23. Okt 2006 17:54

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Hallo,
Zitat:

Zitat von TurboMartin
Bringt in der Schleife viellecht ein Application.ProcressMessages was? :gruebel:

Damit erhöhst Du die Auslastung nur noch. Nicht, dass das bei 100% noch möglich wäre :stupid: .

Gruß
xaromz

Klaus01 23. Okt 2006 18:41

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Vielleicht bringt dich der folgende Thread ein wenig weiter?
Grüße
Klaus

JonnyGuitar 23. Okt 2006 19:12

Re: wait prozedur bewirkt vollständige cpu auslastung
 
servus,

also mein service hat keine oberfläche, und das hndlArr wird wie folgt befüllt:

Delphi-Quellcode:
hndlarr[0] := Event1.Handle;
hndlarr[1] := Event2.Handle;
den vorgeschlagene thread lese ich mir gleich mal durch.


mfg Jonny

JonnyGuitar 23. Okt 2006 19:15

Re: wait prozedur bewirkt vollständige cpu auslastung
 
kurzer nachtrag:

ich habe mir gerade den vorgeschlagenen thread von klaus durchgelesen, aber auch die folgende prozedur
Delphi-Quellcode:
procedure Delay(Milliseconds: Integer);
var
  Tick: DWord;
  Event: THandle;
begin
  Event := GetCurrentThread;
  Tick := GetTickCount + DWord(Milliseconds);
  while Milliseconds > 0 do
    case MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) of
      WAIT_TIMEOUT: Exit;
      WAIT_OBJECT_0: WriteLn('Fails');
    else
      begin
        Application.ProcessMessages;
        Milliseconds := Tick - GetTickcount;
      end;
    end;
end;
bringt 100% cpu auslastung

Klaus01 23. Okt 2006 20:43

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Deine letzte Funktion bringt bei mir in einer Consolenanwendung auch 100% CPU Last.

Die folgende Funktion bringt bei eine CPU Last von 3-4%.

Delphi-Quellcode:

procedure Delay(Milliseconds: Integer);
{by Hagen Redmann}
var
  Tick: DWORD;
  Event: THandle;
begin
  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickCount + DWORD(Milliseconds);
    while (Milliseconds > 0) and
      (MsgWaitForMultipleObjects(1, Event, False, Milliseconds,
      QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      Application.ProcessMessages;
      Milliseconds := Tick - GetTickCount;
    end;
  finally
    CloseHandle(Event);
  end;
end;
Grüße
Klaus

JonnyGuitar 24. Okt 2006 08:17

Re: wait prozedur bewirkt vollständige cpu auslastung
 
moin klaus,

ich kann leider nicht in meinem service application.processmessages benutzen :(


mfg Jonny

Klaus01 24. Okt 2006 08:21

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Nun, von Services habe ich keine Ahnung (hab' noch nie einen programmiert) deshalb jetzt
meine etwas dümmliche Frage: Geht es auch nicht wenn Du die Unit Forms einbindest?

Grüße
Klaus

JonnyGuitar 24. Okt 2006 08:23

Re: wait prozedur bewirkt vollständige cpu auslastung
 
habe ich gerade versucht, dass geht *g*. aber leider bringt der code:

Delphi-Quellcode:
procedure Delay(Milliseconds: Integer);
{by Hagen Redmann}
var
  Tick: DWORD;
//  Event: THandle;
begin
//  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickCount + DWORD(Milliseconds);
    while (Milliseconds > 0) and
      (MsgWaitForMultipleObjects(2, hndlArr, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      Application.ProcessMessages;
      Milliseconds := Tick - GetTickCount;
    end;
  finally
//    CloseHandle(Event);
  end;
end;
auch wieder volle cpu auslastung :(


mfg Jonny

Luckie 24. Okt 2006 08:29

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Ruf doch einfach mal in deinem ursprüngluichen Code Sleep(1) auf.

JonnyGuitar 24. Okt 2006 08:39

Re: wait prozedur bewirkt vollständige cpu auslastung
 
moin luckie,

trotz sleep(1) immer noch volle cpu auslastung...


mfg Jonny

Flocke 24. Okt 2006 08:46

Re: wait prozedur bewirkt vollständige cpu auslastung
 
Zwei Fragen:
1. Rufst du die Routine in einem Thread auf?
2. Warum gibst du in einem Beispiel den aktuellen Thread (GetCurrentThread) als das Objekt an, auf das gewartet werden soll?

negaH 24. Okt 2006 08:49

Re: wait prozedur bewirkt vollständige cpu auslastung
 
@Jonny:

Ist das noch der gleiche Code den du verwendest ? Nein: du kommentierst Zeilen aus die die Funktion vollständig verändern.

Delphi-Quellcode:
procedure Delay(Milliseconds: Integer);
{by Hagen Reddmann}
var
  Tick: DWORD;
  Event: THandle;
begin
  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickCount + DWORD(Milliseconds);
    while (Milliseconds > 0) and
      (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      Application.ProcessMessages;
      Milliseconds := Tick - GetTickCount;
    end;
  finally
    CloseHandle(Event);
  end;
end;
So funktioniert das wunderprächtig, in einem normalem Prozess wie angedacht. Das Event so zu benutzen ist essentiell, es ist nämlich ein niemals signalsierendes Event und darauf baut der Code aktiv auf.

Willst du das abändern dann unter 4 Bedingungen:

Delphi-Quellcode:
procedure Delay(Milliseconds: Integer);
var
  Tick: DWORD;
begin
  Tick := GetTickCount + DWORD(Milliseconds);
  while Milliseconds > 0 do
  begin
    case WaitForMultipleObjects(2, hndlArr, False, Milliseconds, QS_ALLINPUT) of
      WAIT_OBJECT_0 +0 :
        begin
          // Event Nummer 1 signalisiert
        end;
      WAIT_OBJECT_1 +1 :
        begin
          // Event Nummer 2 signalisiert
        end;
      WAIT_TIMEOUT:
        begin
          // nothing todo
          Exit;
        end;
    else
      begin
        // Fehler !! 
      end;
    end;
    Milliseconds := Tick - GetTickCount;
  end;
end;
1.) ein Service wie deiner hat keinen Message Queue
2.) MsgWaitFor...() benötigt einen Message Queue, ergo wird WaitForMultipleObjects() benutzt
3.) du musst bei vorzeitiger Rückkehr von WaitFor..() auch die signalisierenden Events abprüfen. Besonders wenn diese Events sich nur manuell zurücksetzen lassen. Du hast ja eben nichts darüber ausgesagt was für Events das sind und wie sie signalisiert/resetet werden
4.) überpüfe nun ob der obige Code permanent in WAIT_OBJECT_0 oder WAIT_OBJECT_0 +1 rein springt. Sollte dies der Fall sein so ist dein Event Handling falsch. Eventuell musst du die Event mit ResetEvent() zurücksetzen.

Alles in allem kann ich dir garantieren das wenn die Events korrekt benutzt werden die CPU Auslastung entsprechend der Häufigkeit des Auslösens der Events absinken wird. Sind diese natürlich permanent signalisiert so beträgt die CPU Auslastung auch 100%.

Der obige Code ist dermaßen trivial das ein Fehler auszuschließen ist. Wenn also die CPU Auslastung immer noch 100% ist so wird es mit großer Wahrscheinlichkeit ein Fehler in deinem restlichen Code sein (den wir ja nicht kennen).

Gruß Hagen

JonnyGuitar 24. Okt 2006 09:20

Re: wait prozedur bewirkt vollständige cpu auslastung
 
so, mit dem letzten code klappt alles hervorragend,

jedoch sind noch 3 veränderungen zu machen:

Delphi-Quellcode:
procedure Delay(Milliseconds: Integer);
var
  Tick: DWORD;
begin
  Tick := GetTickCount + DWORD(Milliseconds);
  while Milliseconds > 0 do
  begin
    case WaitForMultipleObjects(2, @hndlArr, False, Milliseconds) of
      WAIT_OBJECT_0 +0 :
        begin
          // Event Nummer 1 signalisiert
        end;
      WAIT_OBJECT_0 +1 :
        begin
          // Event Nummer 2 signalisiert
        end;
      WAIT_TIMEOUT:
        begin
          // nothing todo
          Exit;
        end;
    else
      begin
        // Fehler !!
      end;
    end;
    Milliseconds := Tick - GetTickCount;
  end;
end;
so liet die prozessorauslastung bei 0% und ich bin glücklich.

vielen dank an alle

mfg Jonny


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