Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi CPU Auslastung für ein Programm begrenzen (https://www.delphipraxis.net/73441-cpu-auslastung-fuer-ein-programm-begrenzen.html)

Luckie 18. Jul 2006 12:30

Re: CPU Auslastung für ein Programm begrenzen
 
Hast du dir die Beiträge von Klaus und Domink mal durchgelesen? Das sind zwei Lösungsvorschläge, wobei der mit den Threads wohl vorzuziehen wäre.

Flare 18. Jul 2006 12:34

Re: CPU Auslastung für ein Programm begrenzen
 
Bei exakt diesem Code kann ich nicht verstehen, warum er 5-10 Minuten arbeitet. Und man kann am Code noch einiges vereinfachen/verschönern. Zum Beispiel die 2 aufeinanderfolgenen for-Schleifen zu einer zusammenzufassen, iCell brauchst du auch nicht, oder du lässt i weg.

Threads kann ich hier auch vorschlagen und vielleicht solltest du den Code nochmal überarbeiten.


Flare

xaromz 18. Jul 2006 12:41

Re: CPU Auslastung für ein Programm begrenzen
 
Hallo,

ich habe mir mal erlaubt, den Code etwas zu überarbeiten. Es gibt zwar sicher noch mehr zu optimieren, aber ich habe mich auf das Nötigste beschränkt. Erstens sind jetzt ein paar Ressourcen-Schutzblöcke mit 'drin, und zweitens hab ich von Textfile aud TStringlist umgestellt.
Schau' mal, ob das so schneller läuft.
Delphi-Quellcode:
procedure TMain_Form.prCreateXls(iAnzRec : Integer);
var
bl                                         : Boolean;
oleExcelApp, oleExcelSheets, oleExcelWorkb : OleVariant;
i, j, iCount, iRow                     : Integer;
sDate, sFile, sPath, sRow, sXlsFile        : String;
wRC                                        : Word;
SL: TStringList;

begin

  //Paths
  sDate := FormatDateTime('yyyymmdd', Date);
  sFile := 'U:\Programmierung\LOG\Router_Tab\Excel\ROUTES_TAB_' + sDate;
  sPath := '..\Output\ROUTES_Convert_' + sDate + '.txt';

  //Create .xls / Set Column Format / Create Header

  try
    oleExcelApp := CreateOleObject('Excel.Application');
    oleExcelWorkb := oleExcelApp.Workbooks.Add;
    oleExcelSheets := oleExcelworkb.WorkSheets.Add;
    oleExcelSheets.Name := 'Router Tab vom ' + sDate;

    iRow := 1;
    For i := 1 To 7 Do
    Begin
      oleExcelSheets.Columns[i].NumberFormat := '@';
      oleExcelSheets.Cells[iRow, i].Font.FontStyle := 'Bold';
      case i of
        1: oleExcelSheets.Cells[iRow, i].Value := 'Land';
        2: oleExcelSheets.Cells[iRow, i].Value := 'PLZ Von';
        3: oleExcelSheets.Cells[iRow, i].Value := 'PLZ Bis';
        4: oleExcelSheets.Cells[iRow, i].Value := 'O - Sort';
        5: oleExcelSheets.Cells[iRow, i].Value := 'D - Depot';
        6: oleExcelSheets.Cells[iRow, i].Value := 'D - Sort';
        7: oleExcelSheets.Cells[iRow, i].Value := 'Barcode ID';
      end;
    End;


    iCount := 100;
    //Assign .txt File for Input
    SL := TStringList.Create;
    try
      try
        SL.LoadFromFile(sPath);

        iRow := 2;
        for j := 0 to SL.Count - 1 do
        begin
          For i := 1 To 7 Do
          Begin
            sRow := SL[j];
            case i of
              1: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 1, 2);
              2: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 3, 9);
              3: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 12, 9);
              4: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 21, 4);
              5: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 25, 4);
              6: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 29, 4);
              7: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 33, 3);
            end;
          End;

          Inc(iRow);
          //Set Progress in Progress Bar
          If iRow = iCount Then
          Begin
            ProgBar2.Position := Round((100 * iRow) / iAnzRec);
            iCount := iCount + 100;
          End;
        end;
      except
        ShowMessage('Error opening file!');
      end;
    finally
      SL.Free;
    end;

    //Examine whether File is present
    bl := FileExists(sFile + '.xls');
    If bl = True Then
    Begin
      wRC := MessageDlg('File is allready present!' +#13+ 'Clear File?', mtInformation, mbYesNo, 0);
      If wRC = mrYes Then
      Begin
        bl := DeleteFile(sFile + '.xls');
        If bl = False Then
        Begin
          ShowMessage('Error with File Clear!');
        End;
      End
      Else
      Begin
        ShowMessage('File would be Overwritten!');
      End;
    End;



    //Save as .xls File
    sXlsFile := ChangeFileExt(sFile, '.xls');

    Try
      oleExcelWorkb.Close(true, sXlsFile, false);
    Except
      ShowMessage('Save To File Error');
    End;

    //Excel freigeben
  finally
    oleExcelSheets := Unassigned;
    oleExcelWorkb := Unassigned;
    oleExcelApp.Quit;
    oleExcelApp   := Unassigned;
  end;

  ProgBar2.Position := 0;
  lbl_sts_xls.Caption   := 'Export to Excel. OK';
  lbl_sts_xls.Font.Size := 8;
  lbl_sts_xls.Font.Color := clGreen;
  Main_Form.Refresh;

  bitbtn_exit.Enabled := True;
end;
Übrigens: Es sieht so aus, als würde diese Funktion mehrfach aufgerufen. Wenn ja, wie oft bzw. wie sieht der aufrufende Code aus?

Gruß
xaromz

Klaus01 18. Jul 2006 13:02

Re: CPU Auslastung für ein Programm begrenzen
 
Delphi-Quellcode:
 
//Assign .txt File for Input
  {$I-} 
  AssignFile(txtFile, sPath);
  Reset(txtFile);
  {$I+}
  if IOResult = 0 then
  begin
    iCount := 100;
    iRow := 2;

    While Not EOF(txtFile) Do
    Begin

      Application.ProcessMessages;

      Readln(txtFile, sRow);

      //Add sRow to Excel Cells
      For i := 1 To 7 Do
        Begin
          case i of
            1: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 1, 2);
            2: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 3, 9);
            3: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 12, 9);
            4: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 21, 4);
            5: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 25, 4);
            6: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 29, 4);
            7: oleExcelSheets.Cells[iRow, i].Value := Copy(sRow, 33, 3);
          end;
        End;

      iRow := iRow + 1;

      //Set Progress in Progress Bar
      If iRow = iCount Then
      Begin
        ProgBar2.Position := Round((100 * iRow) / iAnzRec);
        iCount := iCount + 100;
      End;

    End;
  end;
  CloseFile(txtFile);
Hallo Andreas,

wenn Du schon mit {$I-} und {$I+} arbeitest
solltest Du auch IOResult in irgendeiner Art und Weise abfragen.

Ansonsten finde ich die Version mit dem Zeileweisen einlesen
im Hinblick auf den Speicherverbrauch schonender als
die Version von xaromz.


Grüße
Klaus

Andidreas 18. Jul 2006 13:14

Re: CPU Auslastung für ein Programm begrenzen
 
Zitat:

Zitat von Luckie
Hast du dir die Beiträge von Klaus und Domink mal durchgelesen? Das sind zwei Lösungsvorschläge, wobei der mit den Threads wohl vorzuziehen wäre.

ich will dich jetzt hier nicht angreifen als mod luckie oder hier nen streit vom zaun brechen, aber ist es mir als foren user nicht erlaubt nach weitern lösungen zu fragen wenn meiner meinung nach das passende noch nicht dabei war???

ich habe deshalb nach weiteren lösungen gefragt weil ich mir unsicher war, ob der vorschlag von klaus01 das gewünschte ergebniss bringt (da ich noch nicht so bewandert bin in der delphi programmierung, und da jemand anders die antwort in frage gestellt hat)
und weil von thread programmierung keine ahnung hab und mir im moment die zeit dazu fehlt für das aktuelle projekt das auszuprobieren...

ich benutze dieses forum hier nicht dafür das mir einer die lösung auf dem silbernen tablett serviert, ich benutze dieses forum dafür in bestehenden artikeln nach lösungen zu suchen und wenn ich nichts passendes finde einen neuen beitrag zu eröffnen um mein problem euch hier zu schildern in der hoffnung hinweise zu bekommen die auf die lösung meines problems hindeuten!!!

soviel dazu von meiner seite...

@flare
warum kannst du nicht verstehen das er hierfür so lange braucht???
ok, ich weiß nicht was die normale verarbeitungs zeit für sowas ist, aber in anbetracht des datenvolumens, find ich das "aktzeptabel"
ok, am code kann ich noch einiges verschönern, er sieht teilweise deshalb so komisch aus, weil ich hierfür die informationen hab zusammen suchen müssen, und ich endlich froh war das es läuft ;)

@xaromz
danke für deine mühe...
ich werd den source code von dir bei gelegenheit mal in mein programm einbauen und testen...

der aufrufende code ist ganz einfach ^^ die procedure wird über einen button auf der form aufgerufen :mgreen:
die procedure läuft also so oft der anwender denn button betätigt... im normal fall nur einmal ;)

Luckie 18. Jul 2006 13:23

Re: CPU Auslastung für ein Programm begrenzen
 
Zitat:

Zitat von Andidreas
ich will dich jetzt hier nicht angreifen als mod luckie oder hier nen streit vom zaun brechen, aber ist es mir als foren user nicht erlaubt nach weitern lösungen zu fragen wenn meiner meinung nach das passende noch nicht dabei war???

ich habe deshalb nach weiteren lösungen gefragt weil ich mir unsicher war, ob der vorschlag von klaus01 das gewünschte ergebniss bringt (da ich noch nicht so bewandert bin in der delphi programmierung, und da jemand anders die antwort in frage gestellt hat)
und weil von thread programmierung keine ahnung hab und mir im moment die zeit dazu fehlt für das aktuelle projekt das auszuprobieren...

Ich habe nur nachgefragt, weil du in deinen weiteren Postings mit keinem Wort auf die Vorschlage von Klaus und Dominik eingegangen bist. Man könnte sich ja auch erstmal damit beschäftigen, um sie dann auch beurteilen zu können.

Andidreas 18. Jul 2006 13:29

Re: CPU Auslastung für ein Programm begrenzen
 
Zitat:

Zitat von Andidreas
@klaus01
nein das application.processmessages hab ich noch nicht drinne...
inwiefern kann mir das helfen bzw. was bewirkt das???

@dominik.boehm
ich hab leider noch nicht mit threads gearbeitet bzw. einen thread programmiert!

*hierzu kein kommentar von mir*

naja... imho haben wir etwas aneinander vorbeigeredet ;)

Klaus01 18. Jul 2006 14:04

Re: CPU Auslastung für ein Programm begrenzen
 
Hallo Andreas,

Application.ProcessMessages ist dann sinnvoll wenn ein Programm
lange Schleifen abzuarbeiten hat. Es ermöglicht es dem Programm
Messages die für das Programm bestimmt sind abzuarbeiten.
Das Programm erscheint dann nicht so, als ob es eingefroren wäre.

Dein Programm würde dann auf minimize oder maximize oder auch
auf andere Ereignisse reagieren.

Sorry, hatte das zu meinem ersten Beitrag hinzugefügt.

Grüße
Klaus

Andidreas 18. Jul 2006 14:07

Re: CPU Auslastung für ein Programm begrenzen
 
ah ok gut danke für denn tipp klaus01
^^ jetzt weiß ich auch warum ich teilweise probleme mit meiner form hatte wenn ich mit anderen applikationen nebenher weitergearbeitet habe...

Der_Unwissende 18. Jul 2006 14:15

Re: CPU Auslastung für ein Programm begrenzen
 
Hi,
@Andidreas Sorry aber als etwas Aussenstehender finde ich deine Kritik, dass du doch nach weiteren Lösungen fragen kannst etwas nun ja. Natürlich kannst du immer nach weiteren Lösungen fragen, bis dir eine gefällt aber ich denke dass wäre doch irgendwie etwas ignorant. Ich denke das was Luckie sagte war nicht böse gemeint (hast du hoffentlich auch nicht so aufgefasst), aber letztlich sagt er ja nur, dass du da zwei Möglichkeiten hast.
Das du noch nicht mit Threads gearbeitet hast ist ja ok, aber du sagst nirgends, warum das jetzt ein Problem ist. Ich meine du wirst wahrscheinlich mit mehr Techniken nicht gearbeitet haben als umgekehrt, geht doch den meisten so. Aber wenn du eine Technik nicht kennst, dann such doch einfach ein wenig was dazu, zu Threads z.B. in der DP ;-)
Ich meine das nicht böse, ich persönlich fand nur deine Reaktion etwas weit hergeholt.

Was Threads angeht, so ist es recht einfach mit ihnen zu arbeiten. Das gilt überhaupt nicht pauschal, aber für dein Problem. Die Grundlagen liegen allerdings auch hier im Beitrag von xaromz, der sagte ja schon, dass Windows deine Rechenzeit verwaltet. Kein Prozess weiß, wieviel CPU Zeit es bekommt (es denkt immer es hätte 100% CPU Zeit, 100% vom Speicher und sei das Einzigste Programm auf der Welt). Für Threads gilt eigentlich das Selbe (beides ist stark vereinfacht). Jedenfalls schaltet Windows ganz ganz schnell zwischen einzelnen Programmen und Threads hin und her. Ein Programm hat dann immer für eine gewisse Zeit (die das Programm nicht kennt) die CPU und den Speicher. Läuft die Zeit ab, speichert Windows den Zustand und kopiert den zurück, bevor das Programm das nächste mal dran ist.
Hier hast du dann jetzt die Möglichen Probleme beim Threading, laufen zwei Threads parallel, so weißt du nicht wo sich welcher Thread wann befindet. Greifen beide auf ihren Speicher zu, ist das kein Problem. Teilen sie sich aber irgendeinen Bereich, so kann es hier zu Konflikten kommen. Ein Beispiel wäre eine Bank. Sagen wir du hast einen Thread, der etwas abbucht und einen der etwas gutschreibt. Sagen wir noch auf deinem Konto sind gerade 1000 Euro. Der eine Thread möchte 500 Euro gutschreiben, der andere möchte 1000 abbuchen. Die einzelnen Schritte sehen ungefähr so aus:
  1. Hol dir den aktuellen Kontostand
  2. Schreib Betrag gut / zieh Betrag ab
  3. Speicher Kontostand
So, mit nur einem Thread würde es so aussehen, dass du erst (reihenfolge eigentlich egal) 500 Euro bekommst und dann 1000 abgezogen werden, du hättest also noch 500 Euro auf deinem Konto.
Beim Threading laufen beide Prozesse gleichzeitig. Es kann nach jedem der drei Schritte zur Ausführung des jeweils anderen Thread kommen. Ein Problem wäre, wenn sich beide gleichzeitig den alten Kontostand holen (1000 Euro), dann beide den Betrag gutschreiben/abziehen und nun kommt es drauf an, wer zuerst speichert. Wird erst der abgezogene Betrag gespeichert, wäre der letzte Stand der gespeichert wird 1500 Euro (+), gut für dich schlecht für deine Bank. Andersrum würde es aber zu 0 Euro führen (schlecht für dich! und die Bank hätte Geld verloren, auch nicht gut).
Solange du aber einen Thread die eigentliche Arbeit sequentiell machen lässt (er also als einziger auf seinen Daten arbeitet), kann dir das alles egal sein. Da wird der Thread halt als neuer Prozess nebenbei gestartet (und es kommt nie zu einem Konflikt). Wie man das genau macht, entnimmst du am besten einem Tutorial zum Thema Threads oder schaust in die OH. TThread heißt hier das Schlüsselwort.

Was die Zeit angeht, die dein Programm verbraucht, es klingt einfach langsam, da du nur 2,5 MByte an Daten verarbeist. Schau dir einfach mal an, in welcher Zeit ein Grafikprogramm Dateien von >> 10 MByte verarbeitet. Da werden wenige Milisekunden benötigt. Du siehst da schnell warum es langsam wirkt (muss ja nicht so sein).

Gruß Der Unwissende

[EDIT]
Was ProcessMessages angeht, so stimmt das natürlich, was gesagt wurde. Aber Application.ProcessMessages ist ein schlechter Weg. Der Aufruf dieser Methode kostet Zeit, auch wenn mal nichts zu tun ist. Andererseits wird auf Nachrichten (wie dem neu zeichnen) nur reagiert, wenn die Windowsbotschaft dafür auch behandelt werden kann. Man muss also einen Kompromiss zwischen sehr vielen Application.ProcessMessages (sehr langsam) und sehr wenigen (seltenes Neuzeichnen) finden.
Wird ein Thread mit niedrigerer Priorität verwendet, so bekommt der immer die volle Rechenzeit, die zur Verfügung steht. Muss das Fenster neu gezeichnet werden, wird die durch die Applikation höherer Priorität ausgelöst. Dieser Prozess würde dann automatisch Vorrang bekommen. Somit muss man sich keine Gedanken um die Stellen machen, an denen man ein Neuzeichnen erlauben möchte, es passiert automatisch dann und nur dann, wenn es nötig wird.
[/EDIT]


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:31 Uhr.
Seite 2 von 4     12 34      

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