Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi [Bug?] Delphi ist zu langsam? (https://www.delphipraxis.net/124225-%5Bbug-%5D-delphi-ist-zu-langsam.html)

The Riddler 17. Nov 2008 09:37


[Bug?] Delphi ist zu langsam?
 
Klitzekleines Problem mit Turbo Delphi.

Ich habe eine ziemlich lange Funktion, die ziemlich lange etwas macht. Damit der User brav wartet und in der Zwischenzeit nichts anderes macht, wollte ich ein Label welches ausgibt sobald der Vorgang in Gang gesetzt wird. So sieht der Kopf meiner Funktion aus:

Delphi-Quellcode:
begin
   Label14.Caption := 'Status: Working, please wait!';
   Label14.Font.Color := clRed;
if IsAppRunning('xxxx.exe') = true then
 begin
  //viel zu tun hier
 end;
Nur leider, macht Delphi das Label nicht rot und ändert die Caption. Ich war schon am verzweifeln, bis ich ein
Delphi-Quellcode:
Application.ProcessMessages;
hinter das Setzen der Label-Farbe gesetzt habe. Nun geht es, ich frage mich trotzdem wieso ich das so machen muss.

Was genau macht Application.ProcessMessages denn, nicht das das noch Einfluss auf die restliche Funktion hat. :?

Thx

Sherlock 17. Nov 2008 09:47

Re: [Bug?] Delphi ist zu langsam?
 
Das ist kein Bug, das ist halt so.
Das ändern der Caption und der Farbe findet schon statt, nur hat Deine Anwendung durch die Ausführung der langen Funktion nicht mehr Gelegenheit, das neu zu zeichnen. Durch Application.ProcessMessages verschaffst Du -bildlich gesprochen- der Anwendung halt etwas Luft, um neu zu zeichnen.

Sherlock

mkinzler 17. Nov 2008 09:52

Re: [Bug?] Delphi ist zu langsam?
 
Es gibt Rechenzeit ab.

The Riddler 17. Nov 2008 09:55

Re: [Bug?] Delphi ist zu langsam?
 
k thx

Bernhard Geyer 17. Nov 2008 09:55

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von The Riddler
Was genau macht Application.ProcessMessages denn, nicht das das noch Einfluss auf die restliche Funktion hat. :?

Du mußt nur verhindern das der user z.B. nochmal den Startknoten für deine Berechnung startet.

divBy0 17. Nov 2008 09:57

Re: [Bug?] Delphi ist zu langsam?
 
Vielleicht solltest du die Funktion in einen Thread auslagern.

The Riddler 17. Nov 2008 09:58

Re: [Bug?] Delphi ist zu langsam?
 
Naja, der Durchlauf der Funktion dauert atm um die 40 Sekunden (dank schlechter Programmierkunst :mrgreen: ), was aber daran liegt das viele Dateien bearbeitet und ersetzt werden. Bringt das etwas sowas in nen Thread auszulagern?

mkinzler 17. Nov 2008 10:00

Re: [Bug?] Delphi ist zu langsam?
 
Man könnte dann im restlichen Programm weiterarbeiten

The Riddler 17. Nov 2008 10:00

Re: [Bug?] Delphi ist zu langsam?
 
Achso, dass muss ja dann nicht sein, die Funktion ist die eigentlich einzige Aktion die man machen kann. ;)

Sir Rufo 17. Nov 2008 10:03

Re: [Bug?] Delphi ist zu langsam?
 
Jepp ein Thread ist genau das Richtige dafür.

Sollte es möglich sein, dass die lange Berechnung mehrere Schritte durchführt, kann man dem Benutzer sogar mitteilen, wo die Berechnung gerade ist (manchmal kann man sogar sagen, wieviel Prozent schon abgearbeitet sind, vielleicht sogar wie lange es wohl noch dauert).

Für die Kurzweil des Benutzers kann man dann im Vordergrund ein lustiges Video oder auch die Fische von den Desktop-Widgets anzeigen lassen :mrgreen:

Deine User/Kunden werden dankbar sein ...

cu

Oliver

alzaimar 17. Nov 2008 10:17

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von Sir Rufo
Jepp ein Thread ist genau das Richtige dafür.

Äh... Nö. Was soll der Anwender im Vordergrund anderes tun, wenn im Hintergrund der Thread abläuft?

Zitat:

Zitat von Sir Rufo
Deine User/Kunden werden dankbar sein ...

Nun ja, eher herablassend lächeln. Der Spieltrieb lässt ab einem gewissen Alter stark nach.

Mach lieber Folgendes (das ist einfacher und für Deinen Anwendungsfall genauso gut):
Wenn Du z.B. eine Liste von Dateien hast, mit denen etwas geschieht, dann pack eine Progressbar auf die Form und dann das hier:
Delphi-Quellcode:
Procedure TForm1.ProcessMyFiles (Files : TStrings);
Var
  i : Integer;

Begin
  CancelButtonPressed := False; // Privates Boolean-Feld deiner Form
// Der Benutzer kann auf einen 'Abbruch' Knopf (CancelButton) drücken, siehe unten
  ProgressBar.Max := Files.Count+1;
  ProgressBar.Min := 0;
  For i:=0 to Files.Count Do Begin
    ProgressBar.Position := i+1;
    ProcessOneFile(Files[i]); // Eine Datei verarbeiten
    Application.ProcessMessages; // Mausbewegungen und Buttonclicks abarbeiten lassen
    If CancelButtonPressed Then Break; // Abburch gedrückt? Na dann: Abbruch!
  End;
End;

Procedure TForm1.CancelButtonClick (Sender : TObject);
Begin
  CancelButtonPressed := True;
End;
So sähe das schon etwas hübscher aus. Wenn nun jedoch das 'ProcessOneFile' länger als ungefähr 5 Sekunden braucht, sagt die Ergonomie-Lehre, das man noch zusätzliche Informationen anzeigen sollte. Der Anwender soll nicht denken, das die Büchse hängt.
Also kannst Du z.B. in einer zweiten Progressbar den Fortschritt innerhalb der Datei anzeigen.

Wichtig ist, das man ab und an 'Application.ProcessMessages' aufruft. Was die Routine macht? Nun, alle Interaktionen, also Tastendrücke, Mausklicks und -bewegungen etc. werden an die Anwendung in eine Botschaftsliste (Messagequeue) gepackt. Die Anwendung arbeitet nun im Leerlauf immer diese Liste ab, sodaß eben sofort auf Button-Clicks etc. reagiert wird. Das siehst Du nicht, das macht das Application-Objekt alleine.

Wenn Du aber nun rumrechnest, kommt die Application nicht mehr dazu, also musst Du ihr ab und an die Arbeit abnehmen.

Wenn Du natürlich zu oft Application.ProcessMessages aufrufst, dann verlangsamst Du deine Arbeit. Daher kannst Du z.B. bei einem Zähler nur jedes 100ste Mal die Messagequeue abarbeiten lassen. Das passt schon.

Und der Abbruch-Button gibt dem Anwender die totale Kontrolle.

Wozu ein Thread, wenn der Anwender doch nichts anderes machen kann?

igel457 17. Nov 2008 10:53

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von alzaimar
Wozu ein Thread, wenn der Anwender doch nichts anderes machen kann?

Es gibt nur einen Grund: Besseres Programmdesign. Wenn du mit Threads programmierst, kannst du die Berechnungen zum Beispiel auf mehrere Prozessorkerne aufteilen und somit auf Multicoreprozessoren schneller zu einem Ergebnis kommen.

Delphi-Quellcode:
procedure MachWas;
begin
  Thread := TMeinThread.Create;
  Thread.Resume;
  while not Thread.Terminated do
  begin
    Application.ProcessMessages;
    Sleep(10);
  end;
  Thread.Free;
end;

Sir Rufo 17. Nov 2008 10:54

Re: [Bug?] Delphi ist zu langsam?
 
Also eine lange Berechnung interaktiv durchzuführen und mit Application.ProcessMessages die Anwendung dazu zu bringen ab und an die Anzeige zu refreshen halte ich nicht wirklich für einen guten Programmierstil.

Selbst das Minimieren und dann Wiederherstellen einer solchen Anwendung ist auf Gedeih und Verderb davon abhängig, ob dann auch vielleicht ein Application.ProcessMessages kommt.

Eine Anwendung die sich nicht mehr richtig anfühlt (minimieren - wiederherstellen - Fensterinhalt ist grau) wird oft auch einfach nur beendet. Es zeugt von schlechter Programmierung oder auch von Arroganz, wenn man den Anwender auf die Stufe eines Dummchens heruntersetzt - der soll halt gefälligst warten, ich melde mich schon, wenn was passiert, solange ist halt Schicht im Schacht.

Mit der Jedi-VCL-Komponente TJvThread sollte es eigentlich jedem möglich eine längere Berechnung in einem Thread ablaufen zu lassen, so dass es keinen Grund gibt, dieses nicht zu tun.

Aber das ist nur meine Sicht der Dinge ... ITW habe ich schon viele Negativ-Beispiele gesehen ...

cu

Oliver

The Riddler 17. Nov 2008 11:07

Re: [Bug?] Delphi ist zu langsam?
 
Ja, ich lasse ja bereits eine ProgressBar anzeigen wie weit der Prozess fortgeschritten ist. Da teilweise ~240 Strings in einer Datei ersetzt werden, kann es aber ~15s für eine Datei dauernd bis dann der Fortschrittsbalken einen Schritt nach vorn geht. :-(

Fremdkomponenten wie JEDI möchte ich ehrlich gesagt nicht verwenden...

mkinzler 17. Nov 2008 11:13

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Fremdkomponenten wie JEDI möchte ich ehrlich gesagt nicht verwenden...
Und warum?

jbg 17. Nov 2008 11:14

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von mkinzler
Es gibt Rechenzeit ab.

Ganz im Gegenteil. Application.ProcessMessages zieht 100% CPU Last (bei einer CPU) an sich. Nur wir die Zeit für die Botschaftsverarbeitung genutzt. Ein "while not Terminated do Application.ProcessMessage;" bremst alle anderen Anwendungen aus, lässt deine Anwendung aber ratzfatz reagieren.

Sir Rufo 17. Nov 2008 12:00

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von The Riddler
Fremdkomponenten wie JEDI möchte ich ehrlich gesagt nicht verwenden...

Die brauchst Du auch nur dann verwenden, wenn Du es nicht schaffst eine ThreadKlasse selber zu erstellen.

Das ist dann also "Threads 4 Dummies" :mrgreen:

cu

Oliver

divBy0 17. Nov 2008 13:05

Re: [Bug?] Delphi ist zu langsam?
 
Bis jetzt bin ich mit Threads ganz gut gefahren, auch wenn's nur mal um eine Funktion oder ging, die Zeit gebraucht hat.

Anschauen würde ich mir das schon, lohnt sich.

Sir Rufo 17. Nov 2008 14:28

Re: [Bug?] Delphi ist zu langsam?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also für alle die mal einen Thread benutzen wollen (sollen, müssen oder wie auch immer) und sich mit Händen und Füßen gegen irgendwelche Komponenten-Sammlungen welcher Art auch immer wehren, hier ein Thread-Gerüst mit angehängtem Beispiel-Projekt.

Ich war auch bemüht mittels Compiler-Schalter diverse Features in das Thread-Gerüst zu packen:

- Progress
- Status
- Events
- Datenübergabe an Thread
- CriticalSections
- Datenbank-Zugriffe

cu

Oliver

turboPASCAL 17. Nov 2008 14:32

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Also für alle die mal einen Thread benutzen wollen (sollen, müssen oder wie auch immer) und sich mit Händen und Füßen gegen irgendwelche Komponenten-Sammlungen welcher Art auch immer wehren
Autsch. Na das sollte man ohne eine externe Kompo. schon können müssen als Programierer. Wenn nicht Lernen soll da schon helfen. ;)

// Edit:

@Sir Rufo, schickes Demo. Für einen Anfänger aber ggf. zu viel Zeugs in einem Programm.
Einzele Programme ürden für mer Übersichtlichkeit sorgen.

Sir Rufo 17. Nov 2008 14:37

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von turboPASCAL
Autsch. Na das sollte man ohne eine externe Kompo. schon können müssen als Programierer. Wenn nicht Lernen soll da schon helfen. ;)

Jo, aber irgendwann muss man damit anfangen, um zu sehen, so schlimm ist das gar nicht ;-)
Sehen wir es mal als Motivations-Steigerung.

cu

Oliver

jfheins 17. Nov 2008 14:38

Re: [Bug?] Delphi ist zu langsam?
 
Eventuell würde es schon helfen, wenn man nicht jedes Byte der Datei einzeln von der Festplatte anfordern würde :stupid:

Threads würden also das Problem auslagern (statt dem Mainform wartet eben der Thread 90% der Zeit auf die Festplatte) aber wozu das, wenn man das Problem eliminieren kann?

Alternative: Eine Flash-SSD verwenden, die k liefert auch einzelne Bytes zügig :mrgreen:

Sir Rufo 17. Nov 2008 14:40

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von jfheins
Alternative: Eine Flash-SSD verwenden, die kiefert auch einzelne Bytes zügig :mrgreen:

Scheint sich hier um eine Schumi-Festplatte zu handeln, turbo schnell, weil 10cm Kiefer gelegt :mrgreen:

turboPASCAL 17. Nov 2008 14:48

Re: [Bug?] Delphi ist zu langsam?
 
Verflixt das Fehlerle wollt ich auch ihm grad unter die Nase kiefern halten. :mrgreen:

Sir Rufo 17. Nov 2008 14:50

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von turboPASCAL
Verflixt das Fehlerle wollt ich auch ihm grad unter die Nase kiefern halten. :mrgreen:

Wer im Glashaus sitzt ...

- aber wir rutschen gerade ins OT :mrgreen: ... nicht das das noch Mecker vom Meister gibt -

jfheins 17. Nov 2008 14:51

Re: [Bug?] Delphi ist zu langsam?
 
Ich kiefer euch gleich einen :mrgreen:

Oder habt ihr einen über den Durst gekiefert? :stupid:

The Riddler 17. Nov 2008 14:57

Re: [Bug?] Delphi ist zu langsam?
 
Wo ist Luckie wenn man ihn mal braucht zum Spam-Aufhalten? :gruebel:

Naja, ich guck mir mal Threads und nen "Buffer" an, thx. :stupid:

Sir Rufo 17. Nov 2008 15:00

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von The Riddler
Wo ist Luckie wenn man ihn mal braucht zum Spam-Aufhalten? :gruebel:

jetzt und in den nächsten 18 Jahren :gruebel: im Zweifel Kind hüten
Zitat:

Zitat von The Riddler
Naja, ich guck mir mal Threads und nen "Buffer" an, thx. :stupid:

geht doch ;-)

Noedel 17. Nov 2008 15:02

Re: [Bug?] Delphi ist zu langsam?
 
The Riddler , um zur frage zurückzukommen :

-> benutz doch ne statusbar... mit der kannst du das so machen wie du´s vorher im label versucht hattest

Sir Rufo 17. Nov 2008 15:08

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von Noedel
benutz doch ne statusbar... mit der kannst du das so machen wie du´s vorher im label versucht hattest

und das hilft einem dabei eine blockierende Anwendung flüssig zu machen :shock:

The Riddler 17. Nov 2008 15:10

Re: [Bug?] Delphi ist zu langsam?
 
Ich hab es ja bereits gelöst mit ProgressBars (zwei) und nem Label. Der Anwender sollte also nicht länger als 5s denken das das Programm eingefroren ist. ;=)

Übrigens kommt es mir gelegen das der User die Funktion nicht abbrechen kann, weil sonst nichts mehr funktionieren würde wenn die Funktion nicht bis zum Ende ausgeführt werden würde. :mrgreen:

jfheins 17. Nov 2008 15:10

Re: [Bug?] Delphi ist zu langsam?
 
Puffern kannst du übrigens ungefähr so:
Delphi-Quellcode:
var
  fs: TFileStream;
  mem: TmemoryStream;
begin
  fs := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive);
  mem := TMemoryStream.Create();
  try
    mem.CopyFrom(fs, 0);
   
    // Mach was mit memstream
   
    fs.CopyFrom(mem, 0);
  finally
    mem.Free;
    fs.Free;
  end;
end;
Andererseits ... durch Byteweisen Zugriff auf eine normale Festplatte förderst du die Flash-SSD-Festplatten, da diese dann einen echten Vorteil bieten. Falls du es schaffst, noch mehr Programmierer zu überreden, Byteweise und ungepuffert Daten zu lesen und zu schreiben, kannst du Arbeitsplätze in diesem Segement nachhaltig sichern :mrgreen:

Sir Rufo 17. Nov 2008 15:16

Re: [Bug?] Delphi ist zu langsam?
 
Zitat:

Zitat von The Riddler
Übrigens kommt es mir gelegen das der User die Funktion nicht abbrechen kann, weil sonst nichts mehr funktionieren würde wenn die Funktion nicht bis zum Ende ausgeführt werden würde. :mrgreen:

Einen Thread kann der User auch nur dann beenden, wenn der Programmierer ihm diese Möglichkeit gibt.

Wenn du mein Beispiel-Programm daran hindern möchtest beendet zu werden, bevor der Thread entsorgt wurde, dann füg doch für das MainForm-Event folgenden Code hinzu:
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := Not Assigned( FMyThread );
end;
cu

Oliver

igel457 17. Nov 2008 15:30

Re: [Bug?] Delphi ist zu langsam?
 
Wenn es mit dem Buffern etwas komfortabler sein soll, kannst du auch die folgende Unit verwenden:
http://andorra.cvs.sourceforge.net/v...s?revision=1.6

Verwendung:
Delphi-Quellcode:
uses
  ..., AdBuffer;

var
  fs: TFileStream;
begin
  fs := TFileStream.Create('C:\test.mp3', fmCreate);
 
  QueryBufferedStream(fs);

  //Gebuffert auf den Stream zugreifen...

  FreeBufferedStream(fs);

  fs.Free;
end;

Apollonius 17. Nov 2008 16:19

Re: [Bug?] Delphi ist zu langsam?
 
Nochmal zur allerersten Frage: Wenn es nur darum geht, dass ein Control sich neuzeichnen soll, ist die Method Update genau richtig. Damit kann es nämlich auch nicht passieren, dass ein weiterer Buttonklick empfangen wird.


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