Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   100 % CPU Last durch Thread (https://www.delphipraxis.net/29251-100-cpu-last-durch-thread.html)

lightline 6. Sep 2004 16:51


100 % CPU Last durch Thread
 
Hallo Leute ich habe folgende Aufgabe zu lössen,

Aus meinem Hauptprogramm starte ich einen Thread der Objekte aus einem TreeView abholt eine Serielle Kommunikation durchführt und das Ergebnis wieder zurück schreibt.

Die Bearbeitung der Daten Objekte läuft in ca 20 ms durch und das Zyklisch, hierbei kommt es auf Performance an un das soll auch so schnell wie möglich passieren. Leider bremst dieser Thread meinen Haupthread so stark ab, dass eine normale Bedienung nicht mehr möglich ist. Ich habe es bereits mit ProcessApplication.Messagess, sleep, niedrigere Thread.Priority usw. probiert, leider ohne vernünftigen Erfolg. Die Durchlaufzeit des Thread steigt um den Faktor 100 - 1000 an und die Applikation (Bedienung) wird nicht deutlich besser.

Wie kann ich der Hauptapplikation mehr Rechenzeit zukommen lassen, bzw. wie kann man die Rechenzeit dynamisch aufteilen. ?

:coder2:

supermuckl 6. Sep 2004 17:36

Re: 100 % CPU Last durch Thread
 
eigentlich macht die aufteilung windows
und das über die prioritäten die du vergeben kannst
ansonsten kannst nur du bestimmen durch den code im thread wie stark er das system belastet
wenn du allerdings synchronisations probleme hast ( was ich denke ) dann kann es auch zu diesem problembild kommen.. das der thread und das hauptformular garnicht 100% brauchen sondern nur der hauptthread auf irgendwas "wartet" und dir das deshalb als ausgelastet vor kommt
?!

lightline 6. Sep 2004 20:13

Re: 100 % CPU Last durch Thread
 
Daran habe ich auch schon gedacht bin mir nur nicht ganz sicher wie ich dem ganzen Herr werden kann. ?!

Der Code dazu:


Delphi-Quellcode:
unit UThreadProcess;

interface

uses
  Classes, Main, Windows, UTBCC;

type
  TProzessThread = class(TThread)
  private
    CycleTime: LongInt;
    procedure UpdateMain;
  protected
    procedure Execute; override;
  public
    constructor Create(Tree: TTreeView);
    destructor Destroy;
  end;
Var  ProzessThread : TProzessThread;
      Connect : Bool;
implementation

constructor TProzessThread.Create(Tree: TTreeView);
Begin
  FreeOnTerminate := True;
  inherited Create(True);
end;

destructor TProzessThread.Destroy;
begin
  inherited Destroy;
end;

procedure TProzessThread.UpdateMain;
begin
  begin
    FMain.EZykluszeit.text:= inttostr( GetTickCount - CycleTime)+' ms';
  end;
end;

procedure TProzessThread.Execute;
Var I    : Integer;
    Node : TTreeNode;
begin
  Repeat
  Begin
    for I := 0 to FMain.Treeview1.Items.Count -1 do
    begin
      Node:= FMain.Treeview1.Items[I];
      TBCC(Node.Data).DataExchange(Node);
      Synchronize(UpdateMain);
    end;
    CycleTime:= GetTickCount;
  end;
  until Terminated
end;

end.
[edit=sakura] [delphi]Tags Mfg, sakura[/edit]

dizzy 6. Sep 2004 22:25

Re: 100 % CPU Last durch Thread
 
Ersteinmal herzlich wilkommen in der DP! :dp:

Zweitens: die [ delphi] [ /delphi]-Tags (ohne Leerzeichen) stellen deinen Code im Beitrag formatiert und gehighlighted dar.

Drittens: Das "inherited" sollte im Costruktor immer als erstes kommen, da du sonst u.U. eine Propertiy setzt, die nachher von den Elternklassen wieder überschrieben wird.
Delphi-Quellcode:
constructor TProzessThread.Create(Tree: TTreeView);
Begin
  inherited Create(True);  <--\
                               |  getauscht
  FreeOnTerminate := True; <--/
end;
Und folgendes ist nicht ganz so koscher:
Delphi-Quellcode:
procedure TProzessThread.Execute;
Var I    : Integer;
    Node : TTreeNode;
begin
  Repeat
  Begin
    for I := 0 to FMain.Treeview1.Items.Count -1 do // HIER KÖNNTE ES KNALLEN,
                                                    // DA UNSYNCHRONISIERTER ZUGRIFF AUF FMAIN
    begin
      Node:= FMain.Treeview1.Items[I];             // HIER AUCH
      TBCC(Node.Data).DataExchange(Node);
      Synchronize(UpdateMain);
    end;
    CycleTime:= GetTickCount;
  end;
  until Terminated
end;

end.
Das "begin" und "end" bei einer repeat..until-Schleife kannst du dir übrigends sparen ;).
Die Zugriffe würde ich vermeiden, indem du deiner Threadklasse ein paar Variablen spendierst, und diese mit den nötigen Werten bei der Erzeugung füllst. Somit kannst du nachher schön auf Variablen des Threads zugreifen, ohne solche "Kreuzgriffe" auf's Formular. Ist auf jeden Fall sauberer, auch wenn das jetzige klappt.

Dann solltest du, um das Problem der Auslastung zu verringern nach dem createn des Threads die seine Priority verringern (da hilft die ).
Aber trotzdem wirst du auch bei tpIdle immer 100% Gesamtlast haben, da dein Programm dann ja immer zum Zuge kommt, wenn nichts anderes ansteht. Nur lässt es jetzt jedem anderen Thread/Prozess den Vortritt.
Ein kleiner Vermutstropfen: Der Synchronized-Aufruf, aber es ist ja nur einer, und lässt sich wahrscheinlich auch schwer vermeiden ;).

Ich hoffe, ich konnte etwas helfen :)
Gruss,
dizzy

lightline 7. Sep 2004 14:41

Re: 100 % CPU Last durch Thread
 
danke erst mal für die schnelle Hilfe !!

Habe aber immer noch das Problem, sobald ich den Thread starte eine CPU Auslastung von 100 % ansteht. Sogar wenn ich die Execute Methode völlig entkerne und nur noch Repeat..Until drin lasse. :gruebel:

Besser wird es erst wenn ich den Thread mit Sleep bremse.

Wie ist es eigentlich mit der SleepEx Methode hat da jemand ein Beispiel für mich wie man es verwendet ???

Luckie 7. Sep 2004 15:03

Re: 100 % CPU Last durch Thread
 
Dass sich dein Programm niocht mehr richtig trotz Thread bedienen läßt ist ja irgendwie logisch. In der Execute Methode greifst du ja ständig auf ein Objekt des Hauptformulares zu. Wie wäre es, wenn du statt dessen die benötigten daten an ein Feld der Threadklasse übergibst?

dizzy 7. Sep 2004 15:18

Re: 100 % CPU Last durch Thread
 
Zitat:

Zitat von lightline
Habe aber immer noch das Problem, sobald ich den Thread starte eine CPU Auslastung von 100 % ansteht.

1) Siehe Luckies Beitrag (hatte ich ja auch schon geschrieben)

2) Es geht dir glaube ich nicht darum, dass dein Programm nicht mehr bedienbar ist, sondern dass im Taskmanager 100% CPU-Auslastung steht, gell?
Das wirst du auch mit einem Thread niedrigster Priorität nicht ändern können, da der ja immer dann an die Reihe kommt, wenn nichts weiter anstehet. Die CPU wird immer in Summe zu 100% ausgelastet (wenn ein Programm läuft), und wenn dein Programm das einzige ist, dann bekommt es trotz niedrigem Rang die CPU, weil ja sonst nix ansteht. Sobald sich ein weiteres Programm aktiv dazugesellt, gibt dein Thread Kapazität ab - eben so viel, wie du durch das Setzen der Priotität zulässt - bei tpIdle z.B. wird dein Thread NIE zum Zuge kommen, wenn gleichzeitig ein anderer Thread höherer Priorität läuft. Läuft nichts sonst, bekommst du alles, also 100% (abzüglich OS-Prozesse, die fallen aber nicht in diese Rechnung).

Das Programm so zu drosseln, dass es IMMER < 100% CPU "verbraucht" ist imho nur auf Umwegen und nicht so einfach erreichbar, aber auch meist unsinnig, da du die Priorität ja steuern kannst - und wenn Kapazität verfügbar ist, warum sollte sie dein Thread nicht nutzen? ;)

gruss,
dizzy

lightline 8. Sep 2004 15:38

Re: 100 % CPU Last durch Thread
 
Habe den Thread soweit bereinigt, dass ich ohne Sync und direkten VCL Aufrufen zurande komme ... funktioniert auch prächtig.
Die Sache mit der CPU Auslastung klingt logisch und ich werde den Taskmanager in dieser Beziehung ab jetzt einfach ignorieren :wink:

Gruber_Hans_12345 8. Sep 2004 15:58

Re: 100 % CPU Last durch Thread
 
Zitat:

Zitat von lightline
Habe den Thread soweit bereinigt, dass ich ohne Sync und direkten VCL Aufrufen zurande komme ... funktioniert auch prächtig.
Die Sache mit der CPU Auslastung klingt logisch und ich werde den Taskmanager in dieser Beziehung ab jetzt einfach ignorieren :wink:

Probier einfach ein sleep(0) ind die Schleife einzubauen, dann solltest keine 100% haben und trotzdem alles fast so funktionieren wie bisher !

Gruss
Hans

d7user1 16. Mär 2014 16:36

AW: 100 % CPU Last durch Thread
 
ich habe genau dasselbe problem. mein TThread ruft intern eine Function auf welche ein paar dinge erledigt die auch mal länger dauern können.
innerhalb dieser Function ist eine Repeat-until-Schleife.

ich pausiere das mit einem
Delphi-Quellcode:
while pausiert do LongDelay(25);
.
die prozessorauslastung bleibt aber konstant auf dem vorherigen wert und sinkt nicht auf 0.

ich meine mich zu erinnern dass der wert zuvor immer auf 0 gesunken ist. warum tut er das nicht?

Delphi-Quellcode:
procedure TGenFunctions.LongDelay(Milliseconds: Integer);
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;
    if Application.Terminated then
     Exit;
    Milliseconds := Tick - GetTickCount;
   end;
 finally
  CloseHandle(Event);
 end;
end;

Luckie 16. Mär 2014 16:45

AW: 100 % CPU Last durch Thread
 
Warum innerhalb eines Threads Application.ProcessMessages; ?

d7user1 16. Mär 2014 17:11

AW: 100 % CPU Last durch Thread
 
ohne Application.ProcessMessages in der Sleep-Methode blockt meine anwendung. warum weiß ich nicht. <- quatsch.

habe die procedure nun so geändert dass über eine boolsche variable geprüft wird ob man ProcessMessages braucht oder nicht.
wenn der aufruf aus einem thread kommt > nein, sonst > ja.

bisher gibt es aber keinen unterschied bezüglich cpu last.

mjustin 16. Mär 2014 17:29

AW: 100 % CPU Last durch Thread
 
Zitat:

Zitat von d7user1 (Beitrag 1252156)
ich pausiere das mit einem
Delphi-Quellcode:
while pausiert do LongDelay(25);
.
die prozessorauslastung bleibt aber konstant auf dem vorherigen wert und sinkt nicht auf 0.

Was spricht denn dagegen einfach ein Sleep(25) zu verwenden? In einem Thread, der momentan mangels Aufgabe in einem 'Pause' Zustand ist, wird ein Sleep(25) keine negativen Auswirkungen auf die Programmausführung haben, auch nicht für den VCL Thread.

d7user1 16. Mär 2014 17:36

AW: 100 % CPU Last durch Thread
 
also ein sleep(25) funktioniert im thread. aber im vcl-thread blockt es mir das ganze programm.

jaenicke 16. Mär 2014 18:00

AW: 100 % CPU Last durch Thread
 
Wenn du eine Single Core CPU hast und dein Thread viel zu tun hat, spricht aber auch gar nichts dagegen, dass der 100% CPU Last erzeugt. Warum sollte die Aufgabe des Threads denn auch unnötig lange brauchen?

Im Process Explorer kannst du auch schauen welcher Thread überhaupt die Auslastung verursacht.

mjustin 16. Mär 2014 18:36

AW: 100 % CPU Last durch Thread
 
Zitat:

Zitat von d7user1 (Beitrag 1252173)
also ein sleep(25) funktioniert im thread. aber im vcl-thread blockt es mir das ganze programm.

Sleep im VCL-Thread blockiert natürlich das Programm. Aber worauf bzw. warum soll denn im VCL-Thread 25 Millisekunden gewartet werden? Wie sieht die Warte-Funktion (LongDelay) jetzt aus?

himitsu 16. Mär 2014 19:28

AW: 100 % CPU Last durch Thread
 
Wenn im Hauptthread nichts gemacht wird (also keine Messages anstehen),
dann ist diese Schleife ständig nur mit Nachsehen beschäftigt, ob es jetzt was gibt und lastet dann mit Nichts den Kern/Thread zu 100% aus.

PS: Selbst ein Sleep(0) kann etwas ausrichten.
Jeder Thread bekommt ja bom Sheduler immer paar Millisekunden zum Arbeiten, bis die anderen Threads auch mal etwas Zeit bekommen. Und Sleep(0) gibt die Restzeit sofort ans Windows zurück.

OlafSt 16. Mär 2014 21:11

AW: 100 % CPU Last durch Thread
 
Wenn ich mir die Execute-Methode da ansehe (von den bösen Zugriffen auf die VCL abgesehen), wundert mich da nichts.

Würde man die Execute-Methode in den Mainthread verlagern und so laufen lassen, wäre die CPU-Last 100%. Warum sollte das also in einem Thread anders sein ? Es ist ein Trugschluß zu glauben, man verlagere seinen Programmcode einfach in einen Thread und *poff*, geht meine CPU-Last auf Null ;)

Ein volles Rohr in einer Endlosschleife laufendes Programm belegt eben auch die komplette Zeit die CPU - egal ob nun im Mainthread oder als Nebenthread. Erst, wenn Pausen ins Spiel kommen (zum Beispiel "nur alle 250ms eine Runde durchs TreeView"), geht die Last auch zurück.

jaenicke 16. Mär 2014 21:21

AW: 100 % CPU Last durch Thread
 
Zitat:

Zitat von OlafSt (Beitrag 1252185)
Wenn ich mir die Execute-Methode da ansehe

Nicht verwechseln. d7user1 ist nicht der Fragesteller von damals.
Aber solche Missverständnisse sind vorprogrammiert, wenn man einen alten Thread kapert statt einen eigenen aufzumachen. ;-)


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