Delphi-PRAXiS

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)

Andidreas 18. Jul 2006 10:42


CPU Auslastung für ein Programm begrenzen
 
Liste der Anhänge anzeigen (Anzahl: 1)
hi @ all,

ich hab mir ein Programm gebastellt, was ein .txt file (Größe ca. 2,5 MB) einließt, und als .xls file (Größe ca. 8,5 MB) ausgibt.
klappt alles wunderbar... nur als ich gestern meinen taskmanager mit angezeigt hab während ich das programm hab laufen lassen, hat mich fast der schlag getroffen....

mein programm schnappt sich denn bei programm start verfügbaren cpu und arbeitsspeicher und belegt diesen für die laufzeit des programmes (ca. 5-10 min.) komplett!!!! (siehe bild)

das find ich gerade nicht toll, da das ein weiter arbeiten am pc unmöglich macht :wall:

gibt es eine möglichkeit das ich denn arbeitsspeiche und cpu begrenze denn sich das programm nehmen will bzw. nehmen darf???

Nils_13 18. Jul 2006 10:44

Re: CPU Auslastung für ein Programm begrenzen
 
Wenn es möglich ist, dann wird dein Programm aber langsamer arbeiten. Dann ist die Frage, was besser ist.

xaromz 18. Jul 2006 10:48

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

ich kann Deinem Screenshot nicht entnehmen, dass das Programm den ganzen Arbeitsspeicher belegt. Da steht doch: "Verfügbar: 144416KB".

Was die Prozessorauslastung angeht: Jedes Programm versucht, so viel Prozessorzeit zu nutzen wir möglich. Das ist auch so gewollt. Eigentlich sollte Windows dafür sorgen, dass auch alle anderen Programme nicht zu kurz kommen. Wenn Du also Dein Programm nicht auf TimeCritical gestellt hast, sollte das kein Problem darstellen. Wenn doch, dann poste mal etwas Code, für Deine Aufgabe scheinen mir 5-10 Min. irgendwie etwas hoch.

Gruß
xaromz

Klaus01 18. Jul 2006 10:48

Re: CPU Auslastung für ein Programm begrenzen
 
Hast Du in der Verarbeitungsroutine, ich nehme an eine Schleife, auch
Delphi-Quellcode:
Application.ProcessMessages
eingebaut?

Wenn nicht ist es schwierig für andere Processe die CPU zu bekommen.
Ich finde es gut wenn ein Programm sich soviel CPU nimmt wie noch da ist,
aber auch nur dann wenn es sich kooperativ verhält.

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.

Grüße
Klaus

sir-archimedes 18. Jul 2006 10:49

Re: CPU Auslastung für ein Programm begrenzen
 
Könntest du die Verarbeitung nicht in einem separaten Thread machen und diesem eine geringere Priorität zuordnen? Dann würde dein Programm zwar immernoch 100% CPU-Last erzeugen, andere Programme würden aber dennoch besser laufen, da die Priorität des Threads geringer ist...

Andidreas 18. Jul 2006 10:50

Re: CPU Auslastung für ein Programm begrenzen
 
@nils_13
ob mein programm 10 min oder 20 min im hintergrund läuft is mir jux
so lang ich an meinem pc vernünftig weiter arbeiten kann, stellt das ja dann kein problem dar wie lang das läuft...
einfach auf minimieren gehen nach programm start und das programm meldet sich dann von selber zu wort wenns fertig is durch en showmessage ^^

xaromz 18. Jul 2006 11:04

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

Zitat von Klaus01
Wenn nicht ist es schwierig für andere Processe die CPU zu bekommen.
Ich finde es gut wenn ein Programm sich soviel CPU nimmt wie noch da ist,
aber auch nucr dann wenn es sich kooperativ verhält.

Wie ich oben schon geschrieben habe, ist es (außer das Programm erhöht die eigene Priorität) schwer, sich nicht kooperativ zu verhalten. Windows lässt es gar nicht zu, dass ein Programm die Ausführung anderer Programme verhindert. Dafür sorgt das Präemptive Multitasking.

Gruß
xaromz

Balu der Bär 18. Jul 2006 11:37

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

Zitat von Klaus01
Hast Du in der Verarbeitungsroutine, ich nehme an eine Schleife, auch
Delphi-Quellcode:
Application.ProcessMessages
eingebaut?

Warum sollte das die CPU-Auslastung mindern? :gruebel:

Andidreas 18. Jul 2006 11:54

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

Zitat von xaromz
Hallo,
ich kann Deinem Screenshot nicht entnehmen, dass das Programm den ganzen Arbeitsspeicher belegt. Da steht doch: "Verfügbar: 144416KB".

stimmt... hab ich übersehen...

Zitat:

Zitat von xaromz
Was die Prozessorauslastung angeht: Jedes Programm versucht, so viel Prozessorzeit zu nutzen wir möglich. Das ist auch so gewollt. Eigentlich sollte Windows dafür sorgen, dass auch alle anderen Programme nicht zu kurz kommen. Wenn Du also Dein Programm nicht auf TimeCritical gestellt hast, sollte das kein Problem darstellen. Wenn doch, dann poste mal etwas Code, für Deine Aufgabe scheinen mir 5-10 Min. irgendwie etwas hoch.
Gruß
xaromz

nein auf timecritical hab ich es nicht gestellt... weiß gar nicht wie das geht :oops:
hmm wieso sollt das zuviel zeit sein 5-10 min???
Source Code werd ich noch posten aber in nem extra beitrag...

@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!

hat sonst noch jemand ne idee wie ich das hinkriege???

Andidreas 18. Jul 2006 11:56

Re: CPU Auslastung für ein Programm begrenzen
 
hier noch der source code von der routine die das excel erstellt:

Delphi-Quellcode:
procedure TMain_Form.prCreateXls(iAnzRec : Integer);

var
bl                                         : Boolean;
oleExcelApp, oleExcelSheets, oleExcelWorkb : OleVariant;
i, iCell, iCount, iRow                     : Integer;
sDate, sFile, sPath, sRow, sXlsFile        : String;
txtFile                                    : TextFile;
wRC                                        : Word;

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
  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 := '@';
  End;


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


  //Assign .txt File for Input
  {$I-}
  AssignFile(txtFile, sPath);
  Reset(txtFile);
  iCount := 100;
  iRow := 2;

  While Not EOF(txtFile) Do
  Begin

    Readln(txtFile, sRow);

    //Add sRow to Excel Cells

    For i := 1 To 7 Do
    Begin
      iCell := i;
      If i = 1 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 1, 2);
      If i = 2 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 3, 9);
      If i = 3 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 12, 9);
      If i = 4 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 21, 4);
      If i = 5 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 25, 4);
      If i = 6 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 29, 4);
      If i = 7 Then oleExcelSheets.Cells[iRow, iCell].Value := Copy(sRow, 33, 3);
    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;

  CloseFile(txtFile);
  {$I+}

  //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
  oleExcelSheets := Unassigned;
  oleExcelWorkb := Unassigned;
  oleExcelApp.Quit;
  oleExcelApp   := Unassigned;

  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;

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]

Andidreas 18. Jul 2006 14:30

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

Zitat von Der_Unwissende
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.

naja ich hab mich nicht unbedingt angegriffen gefühlt, aber ich fand denn beitrag etwas komisch...
was die ignoranz betrifft, sicher frag ich nicht so lange nach bis mir eine lösung passt, aber von denn 2 antworten dich ich bis dahin bekommen hatte, war für mich keine realisierbar bzw. konnte ich mir nicht vorstellen wie mir das helfen sollte... deshalb meine frage nach weiteren lösungen...


danke noch für deine erklärung zum thema threads, ich werd mir mal bei gelegenheit (sobald ich etwas luft hab das mal auszuprobieren) ein beispiel suchen und werd mal probieren das ganze inen thread zu packen...

Edit:
noch was zur laufzeit...
naja ok 2,5 MB sind nicht wirklich viel...
aber immerhin sind es im excel am ende ca. 63.000 Sätze

Flocke 18. Jul 2006 14:51

Re: CPU Auslastung für ein Programm begrenzen
 
Schreib mal, bevor du mit der eigentlichen Schleife anfängst, ein
Delphi-Quellcode:
oleExcelApp.ScreenUpdating := False;
hinzu. Das kann manchmal Wunder wirken...

Michael Habbe 18. Jul 2006 15:57

Re: CPU Auslastung für ein Programm begrenzen
 
Wenn Andreas nun nicht die 63.000 Datensätze erwähnt hätte, ich bin rein rechnerisch auf 72.817 gekommen. Und das ist schon eine ganze Menge, wenn man eine Textdatei zeilenweise einliest. Wobei ich (ein wenig) bezweifle, dass die Methode SL.LoadFromFile wie xaromz schrieb schneller ist.
Wird hier jede einzele Zelle über OLE an Excel übergeben? Ich habe damit noch nicht gearbeitet :gruebel: Würde mich dann nicht wundern, wenn der Performanceverlust daher rührt.

Das Application.ProcessMessages und ProgressBar.Position muss auch nicht jeden Durchlauf ausgeführt werden. Hier reicht es, wenn man der Counter ausgewertet wird und dann z.B.
Delphi-Quellcode:
  if RowCounter mod 100 = 0 then
  begin
    Application.ProcessMessages;
    ProgBar2.Position := RowCounter;
  end;
ausführt.

Zum Thema Threads: würde ich hier auf keinen Fall verwenden. Der Aufwand für die Entwicklung ist ungleich höher, da es so aussieht, als wenn das Programm "nur" die Excel-Tabelle erstellt. Und da wären Threads wohl die Kanonen auf Spatzen. Wenn ein ganzes Verzeichnis mit Dateien konvertiert werden soll, könnte sich das schon rentieren (Stichwort DualCore)

mfg
Michael

Andidreas 18. Jul 2006 19:51

Re: CPU Auslastung für ein Programm begrenzen
 
ja ich übergeb jede zeile per ole an excel...
ich weiß nicht ob es da ne möglichkeit mit blöcken zu arbeiten :gruebel:
müßt ich mal nachschauen ob das evtl. auch geht, würde dann vermutlich schneller gehen...

SirThornberry 18. Jul 2006 19:59

Re: CPU Auslastung für ein Programm begrenzen
 
Was die Lösung mit dem Thread bringen soll ist mir bisher noch unklar. Ob die Arbeit im Hauptthread des Programmes erledigt wird ist doch irrelevant wenn es um die dauer geht. Der Hauptthread wird genau so lange für die Aufgabe brauchen wie ein Extra Thread der mit gleicher Priorität läuft. Anstelle einen neuen Thread mit niederiger Priorität zu erstellen würde ich einfach die Priorität des Hauptthreads heruntersetzen. Durch einen zusätzlichen Thread würde nur zusätzliche Rechenzeit benötigt (weil dann der Hauptthred + der neue Thread Rechenzeit benötigt)

Der_Unwissende 18. Jul 2006 20:19

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

Zitat von SirThornberry
Was die Lösung mit dem Thread bringen soll ist mir bisher noch unklar

Es geht bei der Lösung mit dem Thread nicht um die Rechenzeit an sich, sondern die Verteilung eben dieser Rechenzeit. Egal mit welcher Priorität der Hauptthread läuft, sobald er in einer Schleife hängt bleibt keine Zeit für mehr als diese Schleife. Das heißt, minimieren, maximieren und verschieben des Fensters klappt einfach mal nicht. Benutzt man einen Thread mit geringerer Priorität (es dürfte fast normale reichen), garantiert einfach nur, dass noch Zeit für den Hauptthread bleibt, unabhängig von dem arbeitenden Prozess (der dann in einer Schleife alle Datensätze durchgeht). Natürlich ist das hier eher ein Fork als ein Nebenläufiger Prozess, gibt jedenfalls keine konkurriende Zugriffe.

Andidreas 19. Jul 2006 06:46

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

Zitat von Der_Unwissende
...Das heißt, minimieren, maximieren und verschieben des Fensters klappt einfach mal nicht...

aber dieses problem würde ich ja wenn ich klaus01 richtig verstanden hab auch mit application.processmessages in denn griff kriegen??!!! oder hab ich da was falsch verstanden?? :gruebel:

SirThornberry 19. Jul 2006 06:53

Re: CPU Auslastung für ein Programm begrenzen
 
das hast du richtig verstanden.

Der_Unwissende 19. Jul 2006 08:09

Re: CPU Auslastung für ein Programm begrenzen
 
Hi,
das hast du zwar schon richtig verstanden, aber man sollte da doch ein wenig richtig stellen. Es wird hier so getan als ob ein Thread totalen Overhead darstellt und dich jahrelange Einarbeitung ohne sinn kostet. Also gerade weil du ein so einfaches Problem hast, ist es eigentlich kein Problem das in einen Thread auszulagern. Du musst nur eine Klasse von TThread ableiten und die Execute Methode überschreiben. Das schätze ich mal so mit ca. 5 min Aufwand ab. Sicherlich tippt sich ein Application.ProcessMessages schneller. Bleibt also die Frage nach dem Nutzen.
Also einerseits hast du noch nicht mit Threads gearbeitet und die kommen in nächster Zeit eher nicht aus dem Trend (siehe HyperThreading, MultiCore CPUs usw.). Jedenfalls ist in deinem Fall die eigentliche Schwierigkeit (die Verwaltung konkurrierender Zugriffe) gar nicht vorhanden. Damit kannst du alles was gemacht wird direkt in der Execute-Methode des Threads machen (ohne Rücksicht auf irgendwas).
Application.ProcessMessages verarbeitet alle anstehenden unbehandelten Nachrichten und kehrt dann zurück. Das heißt für dich, sobald diese Funktion aufgerufen wird, wird hier Rechenzeit verbraucht. Wurde dein Form zum Beispiel bewegt, so würde die neue Position jetzt gezeichnet werden. Wurde es nicht bewegt ist trotzdem Rechenzeit weg (auch hier gibt es einen Overhead!).
Bewegst du dein Form, merkt es dein Programm aber erst wenn Application.ProcessMessages aufgerufen wird. Solange du das nicht tust ist dein Form wieder eingefroren. Stellt sich die Frage wann aufrufen? Zu oft führt zu unnötigem Overhead, zu selten führt zu einfrieren. Und dann kommt noch das Problem, dass es auf unterschiedlich schnellen Rechnern unterschiedlich viel Overhead bedeutet.
Mit einem Thread (der in deinem Problem wirklich einfach zu realisieren ist) musst du dich nicht darum kümmern. Der verwaltet die Rechenzeit selbst. Und alle Zeit die zum zeichnen gebraucht wird, wird mit Vorrang (höhere Priorität) zu gewiesen.
Natürlich klappt es mit beiden Wegen (aber siehe auch andere Threads oder Luckies Vorschlag, die Lösung mit Threads ist die eher zu empfehlende). Ich persönlich finde es ist ein wenig der Vergleich zwischen imperativer Programmierung und OOP in Delphi, du kannst beides machen. Objekte bedeuten im ersten Moment eine Menge overhead (Konstruktoren, Destruktoren,...) aber alles in allem... (natürlich Geschmackssache).

Andidreas 19. Jul 2006 08:51

Re: CPU Auslastung für ein Programm begrenzen
 
@der_unwissende
so langsam hast du mir denn thread so schmackhaft gemacht das ich denn unbedingt haben will :mrgreen:

aber zu meinem verständniss wieder eine frage...

application.processmessages hilft mir dabei, das während meine schleife läuft, die das excel erzeugt trotzdem die forum bewegt werden kann etc...
aber es hilft mir nicht dabei denn hauptspeicher zu begrenzen denn mein programm verwenden darf?!

aber wenn ich mir die beiträge hier zum thema threads durchlese, dann hilft mir der thread lediglich dabei das evtl. die rechenzeit bzw. die laufzeit meines programmes verkürzt wird (evtl.)...

aber effektiv kann ich durch einen thread meinem programm immer noch nicht sagen, das es z.b. nur max. 20% des cpu's verwenden darf...
und das ist eigentlich das was ich suche und gern verwende möchte falls es so was geben sollte :gruebel:

Luckie 19. Jul 2006 09:17

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

Zitat von Andidreas
aber effektiv kann ich durch einen thread meinem programm immer noch nicht sagen, das es z.b. nur max. 20% des cpu's verwenden darf...

Und warum? Wenn du einen Thread mit niedriger Priorität erzeugst, dann gibt dein Prozess auch iommer genügend Rechenzeit ab, wenn sie von anderen Programmen benötigt wird.

Ein Thread-Tutorial gibt es übrigens auf meiner Seite: http://delphitutorials.michael-puff.de

robinWie 19. Jul 2006 09:27

Re: CPU Auslastung für ein Programm begrenzen
 
Aber wenn man mal beachtet, dass auf dem Recher 89 Prozesse laufen, ist es kein Wunder wenn der Rechner in die Knie geht :lol:

Andidreas 19. Jul 2006 09:32

Re: CPU Auslastung für ein Programm begrenzen
 
hmmm ja ok, ein thread wäre schon eine möglichkeit (werd ich vermutlich demnächst auch noch ausprobieren)

ich will für das programm denn cpu deshalb so "hart" begrenzen, weil mir das ziemlich egal is wie lang es läuft...
das programm soll einfach im hintergrund laufen und das excel erstellen, egal wie lang es dafür braucht, mir kommt es lediglich nur darauf an, das ich nebenher normal am rechner arbeiten kann...

danke für denn link, werd ich mir mal anschauen

Luckie 19. Jul 2006 09:44

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

Zitat von Andidreas
mir kommt es lediglich nur darauf an, das ich nebenher normal am rechner arbeiten kann...

Und genau das kannst du tun, wenn du dem Thread eine niedrige Priorität gibst. Du kannst es sogar so machen, dass dem Thread nur CPU Zeit zugeteilt wird, wenn der Rechner gar nichts macht.

Andidreas 19. Jul 2006 12:37

Re: CPU Auslastung für ein Programm begrenzen
 
ah ok gut zu wissen...
dann weiß ich ja jetzt wie ich mein problem unter kontrolle bekomme ^^


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