Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi CPU 100% bei mehreren StringGrid-Forms (https://www.delphipraxis.net/182881-cpu-100-bei-mehreren-stringgrid-forms.html)

michele_tedesco 23. Nov 2014 21:07


CPU 100% bei mehreren StringGrid-Forms
 
Hallo Zusammen

Beim Übernehmen einer Delphi2007 Anwendung habe ich ein Problem in XE5, welches ich nicht nachvollziehen kann.

Die Anwendung soll ermöglichen mehrere Formulare zu öffnen, welche eine Liste beinhaltet (StringGrid).
Die alle Listen aller Formulare werden bei einem Client-TCP-Read event aktualisiert.

Die Formulare werden in einer TList geführt und in einer Schlaufe aktualisiert.

Wenn ich 10 solche Anwendungen mit je einer Liste von 10 Forms (also 100 Forms) auf meinem Server starte (Remote Application), dann ist di CPU-Last ca. 40-60%.

Wenn ich die genau gleiche Anwendung in Delphi XE5 kompiliere und im selben (100 Forms) Setup starte, dann ist die CPU immer bei 100%.

Ich habe zuerst die Anwendung in XE5 OHNE das updated der GridLists kompiliert und die CPU-Last ist bei ca. 20%.
Mit dem Zeichnen der GridList eben 100%.

Ich gehen Zeile für Zeile, Zelle für Zelle durch und setzte mit GridList.Cells[] den Wert, welcher aus der TCP Nachricht ankommt.

Gibt es einen markanten Unterschied im "Rendern" der GridList zwischen den beiden Delphi Versionen?

Ich habe auch nach jeder TCP-Nachricht eine Application.ProcessMessages; ergänzt, jedoch hilft das zwar die Listen abzufüllen, die Applikation ist weiterhin nicht bedienbar und die CPU-Last fast immer bei 100%.


Hier die ein Teil der Methode zum Aktualisieren des Forms:
Delphi-Quellcode:
procedure TFormInfoZeit.FormUpdate;
VAR AktPtr    : PZeitRec;
    DataRec   : TDataRec;
    PosRang   : TRangSet;
    AllRang   : TRangSet;
    SubName   : STRING;
    IntData   : TInternalData;
    Index     : LONGINT;
    OverKat   : LONGINT;
    FeldBreite : LONGINT;
    TotBreite : LONGINT;
    FeldNr    : LONGINT;
    FeldCode  : STRING;
    FeldSize  : LONGINT;
    Select    : BOOLEAN;
    DBFlag    : BOOLEAN;
    Str       : STRING;
begin
  (* Fenstergrösse *)
  GridList.Font.Size       := CSizeFont [FontSize];
  GridList.DefaultRowHeight := CSizeHeight[FontSize];
  GridList.ColCount        := MAX(GetFeldAnzahl,1);
  GridList.RowCount        := AnzLine+1;

  (* Titelzeile *)
  TotBreite := 0;
  DBFlag   := FormInfoMain.DBstaffel;
  FOR FeldNr := 1 TO GetFeldAnzahl DO BEGIN
    FeldBreite := ROUND(GetFeldSize(FeldNr)*CSizeWidth[FontSize]);
    GridList.ColWidths[FeldNr-1] := FeldBreite;
    GridList.Cells[FeldNr-1,0]  := GetFeldBez(FeldNr);
    TotBreite := TotBreite+FeldBreite;
    FeldCode := GetFeldCode(FeldNr);
    IF StrLeft(FeldCode,1) <> '#' THEN DBFlag := TRUE;
  END; (* for *)
  GridList.Width := TotBreite+GetFeldAnzahl+3;
  GridList.Height := ROUND(1.03*GridList.RowCount*GridList.DefaultRowHeight+17);
  Self.Height    := GridList.Top+GridList.Height+28;
  Self.Width     := Max(GridList.Left+GridList.Width+10,650);

  AktPtr := FormInfoMain.ZeitList;
  Index := 1;
  WHILE Index < GridList.RowCount DO BEGIN
    IF AktPtr <> NIL THEN BEGIN
      FormInfoMain.DataList_GetData(AktPtr^.Stnr,DataRec);
      IF (DataRec.Kat IN KatSet) AND (AktPtr^.ZeitNr IN PosSet) THEN BEGIN

        (* Ist Datensatz selektiert ? *)
        IF ShowKlausel <> NIL THEN BEGIN
          IF Daten <> NIL THEN Select := Klausel_Auswerten(Daten.DataSet,IntData,ShowKlausel)
                          ELSE Select := Klausel_Auswerten(NIL,IntData,ShowKlausel);
        END (* if *)
        ELSE Select := TRUE;

        (* alles ok *)
        IF Select THEN BEGIN

          (* alle Kolonnen durchlaufen *)
          FOR FeldNr := 1 TO GetFeldAnzahl DO BEGIN
            FeldCode := GetFeldCode(FeldNr);
            FeldSize := GetFeldSize(FeldNr);

            (* Standard-Felder *)
            Str := '';
            IF FeldCode = '#STNR' THEN BEGIN
              Str := IntToStr(AktPtr^.Stnr);
            END (* if *)
            ELSE IF FeldCode = '#NAME' THEN BEGIN
              IF DatenOk AND (FormInfoMain.Kategorie.GetKatTyp(DataRec.Kat) = 'S') THEN Str := GetDataFeld('Staffel')
                                                                                   ELSE Str := DataRec.Name;
            END (* if *)
            ELSE IF FeldCode = '#JG' THEN BEGIN
              IF FormInfoMain.Kategorie.GetKatTyp(DataRec.Kat) = 'S' THEN
                Str := '--'
              ELSE IF AktPtr^.SubNr = 0 THEN BEGIN
                IF DataRec.Jg > 0 THEN Str := ZahlToStr(DataRec.Jg)
                                  ELSE Str := '??';
              END (* if *)
              ELSE Str := '--';
            END (* if *)
            (* Datenbank-Felder *)
            ELSE IF DBflag THEN BEGIN
              IF DatenOk THEN BEGIN
                IF StrLeft(FeldCode,1) = '#' THEN Str := GetDataFeld(StrRight(FeldCode,2))
                                             ELSE Str := GetDataFeld(FeldCode);
              END (* if *)
              ELSE Str := StrFill('-',FeldSize);
            END; (* if *)

            (* Anzeigen *)
            GridList.Cells[FeldNr-1,Index] := Str;
          END; (* for *)
          (* nächste Zeile *)
          INC(Index);
        END; (* if *)
      END; (* if *)
      AktPtr := AktPtr^.Next;
    END (* if *)
    ELSE BEGIN
      GridList.Rows[Index].Clear;
      INC(Index);
    END; (* else *)
  END; (* for *)

  (* Titel setzen *)
  Caption := GetTextAlle('aktuelle Zeiten','temps actuels','tempi attuali','actual times');
  IF (StrLeft(Titel,1) = '/') OR (StrLeft(Titel,1) = '\') THEN
    Caption := Caption+' '+Titel
  ELSE IF Titel <> '' THEN
    Caption := Titel;
end;

himitsu 23. Nov 2014 21:36

AW: CPU 100% bei mehreren StringGrid-Forms
 
BeginUpdate/EndUpdate?

Im TStringGrid (XE3) versteckt sich das als SetUpdateState, welches aber private ist und ich jetzt nicht fand, wie man das aufruft.
[edit] Habs gefunden, es geht über das BeginUpdate jeder/irgendeiner Row und wird dann zurck ans Grid weitergeleidet :freak:, also einfach auf das BeginUpdate der ersten Row losgehen.


Bei jeder einzelnen Zuweisung wird ein Neuzeichnen ausgelöst.
Das kann man optimieren, indem man ganze Zeilen/Rows auf einmal zuweist, oder eben das Update deaktiviert, solange man Vieles schnell zuweist.
http://www.delphipraxis.net/182865-s...palte-1-a.html

michele_tedesco 1. Dez 2014 13:07

AW: CPU 100% bei mehreren StringGrid-Forms
 
Hallo himitsu

Vielen Dank für dein Feeback zum Rendering.
Ich habe das "Zeichnen" um ein Vielfaches (ca. 6-7) Mal schneller gemacht :dancer:

Lösung war perfekt!


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:38 Uhr.

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